Populating Spinners using Retrofit 1.9? - android

Am looking sample program which could dynamically populating Spinner item from server using Retrofit 1.9 but still I couldn't find any sample can someone share if there is any sample regarding this requirement or else share the method.
How it should be done as am new for android bit struggling to find a solution thanks in advance!
Here is my spinneritem class:
public class MySpinnerItem {
public MySpinnerItem(){
}
public MySpinnerItem(String text, Integer value) {
Text = text;
Value = value;
}
public String getText() {
return Text;
}
public void setText(String text) {
Text = text;
}
public Integer getValue() {
return Value;
}
public void setValue(Integer value) {
Value = value;
}
public String Text;
public Integer Value;
}
Here is my spinner adapter:
package first.service.precision.servicefirst;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import java.util.List;
/**
* Created by 4264 on 25-11-2015.
*/
public class MySpinnerAdapter extends ArrayAdapter<MySpinnerItem> {
private Context context;
private List<MySpinnerItem> objects;
public MySpinnerAdapter(Context context, int resource, List<MySpinnerItem> objects) {
super(context, resource, objects);
this.context = context;
this.objects = objects;
}
#Override
public void add(MySpinnerItem object) {
this.objects.add(object);
}
#Override
public int getCount() {
return objects.size();
}
#Override
public MySpinnerItem getItem(int position) {
return objects.get(position);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
TextView label = new TextView(context);
label.setText(objects.get(position).getText());
return label;
}
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent) {
TextView label = new TextView(context);
label.setText(objects.get(position).getText());
return label;
}
}
Here is the fragment where i set adapter for spinners:
package first.service.precision.servicefirst;
/**
* Created by 4264 on 23-11-2015.
*/
import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import com.squareup.otto.Bus;
import java.util.ArrayList;
import java.util.List;
public class NewRequirements extends Fragment {
Bus bus;
MyListAdapter listAdapter;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
List<MySpinnerItem> SbuList = new ArrayList<MySpinnerItem>();
SbuList.add(new MySpinnerItem("Saravanan.R",1));
SbuList.add(new MySpinnerItem("Yogeshwaran",2));
SbuList.add(new MySpinnerItem("Sathesh",3));
SbuList.add(new MySpinnerItem("Barath",4));
SbuList.add(new MySpinnerItem("Deepak",5));
SbuList.add(new MySpinnerItem("Venkat",6));
SbuList.add(new MySpinnerItem("Meena",7));
SbuList.add(new MySpinnerItem("Ram",8));
SbuList.add(new MySpinnerItem("Jegan",9));
View view = inflater.inflate(R.layout.fragment_dialog_claim, container,
false);
final Button btnupdate;
btnupdate = (Button) view.findViewById(R.id.btnAdd);
final Spinner spSbuID = (Spinner) view.findViewById(R.id.spSbuID);
final Spinner spBuID = (Spinner) view.findViewById(R.id.spBuID);
final Spinner spSubBuID = (Spinner) view.findViewById(R.id.spSubBuID);
final Spinner spServiceCategoryID = (Spinner) view.findViewById(R.id.spServiceCategoryID);
final Spinner spServiceSubCategoryID = (Spinner) view.findViewById(R.id.spServiceSubCategoryID);
final EditText txtRequirements=(EditText)view.findViewById(R.id.txtRequirements);
MySpinnerAdapter myadapter = new MySpinnerAdapter(getActivity().getBaseContext(),android.R.layout.simple_spinner_dropdown_item,SbuList);
spSbuID.setAdapter(myadapter);
myadapter = new MySpinnerAdapter(getActivity().getBaseContext(),android.R.layout.simple_spinner_dropdown_item,SbuList);
spBuID.setAdapter(myadapter);
myadapter = new MySpinnerAdapter(getActivity().getBaseContext(),android.R.layout.simple_spinner_dropdown_item,SbuList);
spSubBuID.setAdapter(myadapter);
myadapter = new MySpinnerAdapter(getActivity().getBaseContext(),android.R.layout.simple_spinner_dropdown_item,SbuList);
spServiceCategoryID.setAdapter(myadapter);
myadapter = new MySpinnerAdapter(getActivity().getBaseContext(),android.R.layout.simple_spinner_dropdown_item,SbuList);
spServiceSubCategoryID.setAdapter(myadapter);
try{
Object o;
o = getFragmentManager().findFragmentByTag("add");
Log.v("FIND", o.toString());
}
catch (Exception ex) {
Log.v("FIND", ex.toString());
}
// add.notify();
btnupdate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
LeadRequirementsView objLeadRequirementsView = new LeadRequirementsView();
MySpinnerItem item;
item = (MySpinnerItem)spSbuID.getSelectedItem();
objLeadRequirementsView.setSbuID(item.getValue());
objLeadRequirementsView.setSbuName(item.getText());
item = (MySpinnerItem)spBuID.getSelectedItem();
objLeadRequirementsView.setBuID(item.getValue());
objLeadRequirementsView.setBuName(item.getText());
item = (MySpinnerItem)spSubBuID.getSelectedItem();
objLeadRequirementsView.setSubBuID(item.getValue());
objLeadRequirementsView.setSubBuName(item.getText());
item = (MySpinnerItem)spServiceCategoryID.getSelectedItem();
objLeadRequirementsView.setServiceCategoryID(item.getValue());
objLeadRequirementsView.setServiceCategoryName(item.getText());
item = (MySpinnerItem)spServiceSubCategoryID.getSelectedItem();
objLeadRequirementsView.setServiceSubCategoryID(item.getValue());
objLeadRequirementsView.setServiceSubCategoryName(item.getText());
objLeadRequirementsView.setDescription(txtRequirements.getText().toString());
Add add;
add = (Add)getFragmentManager().findFragmentByTag("add");
add.updateListView(objLeadRequirementsView);
getActivity().getFragmentManager().popBackStack();
}
});
return view;
}
}
My doubt is i have done it using dummy data but i need to bind the json response from the server to my spinner how come i do this.

Below, is a sample for setting the spinner
Spinner spinner = (Spinner) findViewById(R.id.spinner1);
ArrayAdapter<String> adapter;
List<String> data;
data = new ArrayList<>();
for (int i = 0; i < 20; i++)
data.add("Data " + (i + 1));
adapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, data);
spinner.setAdapter(adapter);
Here data is a dummy data , in your case it will be dummy data.

first create theretrofitapi interface
/**
* reCreated by goodlife on 1/11/2016.
*/
import java.util.List;
import retrofit.Callback;
import retrofit.client.Response;
import retrofit.http.Field;
import retrofit.http.FormUrlEncoded;
import retrofit.http.GET;
import retrofit.http.POST;
/**
* Created by Belal on 11/5/2015.
*/
public interface RetrofitInternetApi {
//#FormUrlEncoded, we have to write this if we want to send post data to the server.
//#POST, because we are using an HTTP Post request we have written this.
// Inside it we have the URL of the script that will be receiving the post request.
// Note that the URL is excluding the root URL. And we have defined the root URL in our MainActivity.
//#Field(“key”) String variable inside key we have to write what we have written inside $_POST[‘key’] in our script.
// And we have to specify it for all the values we are going to send.
//Callback<Response> callback it is also inside the retrofit library. It will receive the output from the server.
//But this is only an interface and the method is abstract.
//We will define the method inside fetchDepartmentName() method that is declared inside MainActivity.java.
#GET("/getDepartmentName.php")
public void getDepartmentName(Callback<List<DepartmentNoRealm>> response);
}
then create the function
private void fetchDepartmentName(){
//Creating a rest adapter
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint(ROOT_URL)
.build();
//Creating an object of our api interface
RetrofitInternetApi retrofitInternetApi = restAdapter.create(RetrofitInternetApi.class);
//While the app fetched data we are displaying a progress dialog
final ProgressDialog loading = ProgressDialog.show(getActivity(), "Fetching Data", "Please wait...", false, false);
//Defining the method
retrofitInternetApi.getDepartmentName(new Callback<List<DepartmentNoRealm>>() {
#Override
public void success(List<DepartmentNoRealm> list, Response response) {
//Dismissing the loading progressbar
loading.dismiss();
Log.d("JSON LIST",list.toString());
//Storing the data in our list
departmentNoRealmList = list;
//Calling a method to show the list
showListinSpinner(); }
#Override
public void failure(RetrofitError error) {
//you can handle the errors here
}
});
}
then create a class model
package myafya.safaricom.co.ke.myafya.model.realm;
/**
* Created by 001557 on 1/13/2016.
*/
public class DepartmentNoRealm {
public int departmentID;
public String departmentName;
public String departmentURLimage;
public int getDepartmentID() {
return departmentID;
}
public void setDepartmentID(int departmentID) {
this.departmentID = departmentID;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public String getDepartmentURLimage() {
return departmentURLimage;
}
public void setDepartmentURLimage(String departmentURLimage) {
this.departmentURLimage = departmentURLimage;
}
}
now the code showList in Spinner
//Our method to show list
private void showListinSpinner(){
//String array to store all the book names
String[] items = new String[departmentNoRealmList.size()];
//Traversing through the whole list to get all the names
for(int i=0; i<departmentNoRealmList.size(); i++){
//Storing names to string array
items[i] = departmentNoRealmList.get(i).getDepartmentName();
}
//Spinner spinner = (Spinner) findViewById(R.id.spinner1);
ArrayAdapter<String> adapter;
adapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, items);
//setting adapter to spinner
spinnerDepartments.setAdapter(adapter);
//Creating an array adapter for list view
}
Then SHARE IT AND MAKE IT EASY
MY JSON WAS
[
{
"departmentID": "1",
"departmentName": "Enterprise Business Unit (EBU)",
"departmentURLimage": "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcSKOZmGNAA08NbHwRJrloAouWqs6r4x7BGXY4k-ULWiHuPEobHI"
},
{
"departmentID": "2",
"departmentName": "Consumer Business Unit (CBU)",
"departmentURLimage": "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcQ0IAFhZ52KiG_0ck5VbBxweZWf_MEA9eRmgHAEr6CG-rUG_a2QEQ"
}
]

try {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constants.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
APIService service = retrofit.create(APIService.class);
Call<List<People>> call = service.getYear(user_id);
call.enqueue(new Callback<List<People>>()
{
#Override
public void onResponse(Response<List<People>> response, Retrofit retrofit) {
posts = response.body();
String[] s =new String[posts.size()];
for(int i=0;i<posts.size();i++)
{
s[i]= posts.get(i).getYear();
final ArrayAdapter a = new ArrayAdapter(getApplicationContext(), android.R.layout.simple_spinner_item, s);
a.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//Setting the ArrayAdapter data on the Spinner
Branch.setAdapter(a);
}
}
#Override
public void onFailure(Throwable t) { }
});
} catch (Exception e) {
Log.d("onResponse", "There is an error");
}
}

Related

GridView Always Scroll To The Top After Success Load Next Page

I face a difficulty when working using recyclerview and Gridview. The problem is when my application success load next page (next data), the recyclerview always back to the top.
I want the recyclerview start from last index.
Example : First page load 10 items, after success loan next page, the recycler view start scrolling from item 8.
For resolve that problem, i have tried all the solution on stackoverflow still get nothing.
Here are my code :
package com.putuguna.sitehinduapk.adapters;
import android.content.Context;
import android.content.Intent;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import com.bumptech.glide.Glide;
import com.putuguna.sitehinduapk.R;
import com.putuguna.sitehinduapk.activities.DetailBlogPostActivity;
import com.putuguna.sitehinduapk.models.listposts.ItemPostModel;
import com.putuguna.sitehinduapk.utils.GlobalFunction;
import com.putuguna.sitehinduapk.utils.GlobalVariable;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public abstract class ListPostAdapter extends RecyclerView.Adapter<ListPostAdapter.ViewHolder>{
private List<ItemPostModel> mListPost;
private Context mContext;
public ListPostAdapter(List<ItemPostModel> mListPost, Context mContext) {
this.mListPost = mListPost;
this.mContext = mContext;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(mContext);
View view = inflater.inflate(R.layout.adapter_item_list_post, null);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, final int position) {
final ItemPostModel post = mListPost.get(position);
List<String> listURL = extractUrls(post.getContentPosting());
Glide.with(mContext)
.load(listURL.get(0))
.into(holder.ivImagePost);
holder.tvTitle.setText(post.getTitle());
holder.llItemPost.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//TO DO OnClick
}
});
List<String> listLabel = post.getListLabel();
String labelPost="";
for(int i=0; i<listLabel.size();i++){
labelPost += "#"+listLabel.get(i) + " ";
}
holder.tvLabel.setText(labelPost);
if ((position >= getItemCount() - 1))
load();
}
public abstract void load();
#Override
public int getItemCount() {
return mListPost.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder{
public ImageView ivImagePost;
public TextView tvTitle;
public LinearLayout llItemPost;
public TextView tvLabel;
public ViewHolder(View itemView) {
super(itemView);
ivImagePost = (ImageView) itemView.findViewById(R.id.iv_image_post);
tvTitle = (TextView) itemView.findViewById(R.id.tv_blog_title);
llItemPost = (LinearLayout) itemView.findViewById(R.id.ll_item_post);
tvLabel = (TextView) itemView.findViewById(R.id.textview_label_adapter);
}
}
public static List<String> extractUrls(String input) {
List<String> result = new ArrayList<String>();
Pattern pattern = Pattern.compile(
"\\b(((ht|f)tp(s?)\\:\\/\\/|~\\/|\\/)|www.)" +
"(\\w+:\\w+#)?(([-\\w]+\\.)+(com|org|net|gov" +
"|mil|biz|info|mobi|name|aero|jobs|museum" +
"|travel|[a-z]{2}))(:[\\d]{1,5})?" +
"(((\\/([-\\w~!$+|.,=]|%[a-f\\d]{2})+)+|\\/)+|\\?|#)?" +
"((\\?([-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?" +
"([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)" +
"(&(?:[-\\w~!$+|.,*:]|%[a-f\\d{2}])+=?" +
"([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)*)*" +
"(#([-\\w~!$+|.,*:=]|%[a-f\\d]{2})*)?\\b");
Matcher matcher = pattern.matcher(input);
while (matcher.find()) {
result.add(matcher.group());
}
return result;
}
}
This code of MainActivity.java
private void getListPost(){
mSwipeRefreshLayout.setRefreshing(true);
String nextPageToken = GlobalFunction.getStrings(this, GlobalVariable.keySharedPreference.TOKEN_PAGINATION);
BloggerApiService apiService = BloggerApiClient.getClient().create(BloggerApiService.class);
Call<ListPostModel> call = apiService.getListPost(GlobalVariable.APP_KEY_V3);
call.enqueue(new Callback<ListPostModel>() {
#Override
public void onResponse(Call<ListPostModel> call, Response<ListPostModel> response) {
ListPostModel listpost = response.body();
initDataView(listpost);
mSwipeRefreshLayout.setRefreshing(false);
}
#Override
public void onFailure(Call<ListPostModel> call, Throwable t) {
mSwipeRefreshLayout.setRefreshing(false);
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
/**
* this method used for post (next page)
*/
private void getNextListPost(){
mSwipeRefreshLayout.setRefreshing(true);
String nextPageToken = GlobalFunction.getStrings(this, GlobalVariable.keySharedPreference.TOKEN_PAGINATION);
BloggerApiService apiService = BloggerApiClient.getClient().create(BloggerApiService.class);
Call<ListPostModel> call = apiService.getNexPageListPost(GlobalVariable.APP_KEY_V3,nextPageToken);
call.enqueue(new Callback<ListPostModel>() {
#Override
public void onResponse(Call<ListPostModel> call, Response<ListPostModel> response) {
ListPostModel listpost = response.body();
initDataView2(listpost);
mSwipeRefreshLayout.setRefreshing(false);
}
#Override
public void onFailure(Call<ListPostModel> call, Throwable t) {
mSwipeRefreshLayout.setRefreshing(false);
Toast.makeText(MainActivity.this, t.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
#Override
public void onRefresh() {
mListPost.clear();
getListPost();
}
private void initDataView(ListPostModel listpost){
GlobalFunction.saveString(this,GlobalVariable.keySharedPreference.TOKEN_PAGINATION, listpost.getNextPageToken());
mListPost.addAll(listpost.getListItemsPost());
mPostAdapter = new ListPostAdapter(mListPost, this) {
#Override
public void load() {
ItemPostModel item = mListPost.get(mListPost.size()-1);
getNextListPost();
}
};
mRecyclerviewPost.setAdapter(mPostAdapter);
//mPostAdapter.notifyDataSetChanged();
mRecyclerviewPost.setHasFixedSize(true);
mGridViewLayoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
mGridViewLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
mRecyclerviewPost.setLayoutManager(mGridViewLayoutManager);
}
/**
* this method used for set view (next page)
* #param listpost
*/
private void initDataView2(ListPostModel listpost){
GlobalFunction.saveString(this,GlobalVariable.keySharedPreference.TOKEN_PAGINATION, listpost.getNextPageToken());
final String nextPageToken = GlobalFunction.getStrings(this, GlobalVariable.keySharedPreference.TOKEN_PAGINATION);
List<ItemPostModel> itemNextPost = listpost.getListItemsPost();
// itemNextPost.addAll(mListPost);
mListPost.addAll(itemNextPost);
mPostAdapter = new ListPostAdapter(mListPost, this) {
#Override
public void load() {
ItemPostModel item = mListPost.get(mListPost.size()-1);
if(nextPageToken==null){
}else{
getNextListPost();
}
}
};
mRecyclerviewPost.setAdapter(mPostAdapter);
mRecyclerviewPost.setHasFixedSize(true);
mGridViewLayoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
mGridViewLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
mRecyclerviewPost.setLayoutManager(mGridViewLayoutManager);
an
}
Any suggestion will be appreciated.
The problem with the code is, your resetting the complete data again into your adapter and setting it to RecyclerView again, That's why it is re instanced everything in RecyclerView and i.e scrolling to top. Instead of that you can try something like just add /append the updated data into the list ( where you holds the data ) and then just call the adapter.notifyDataSetChanged(); method. automatically it will add the updated data and you no need to set the recycler view again.
Probably for your case you need to change your initDataView2() mehtod like below
private void initDataView2(ListPostModel listpost){
GlobalFunction.saveString(this,GlobalVariable.keySharedPreference.TOKEN_PAGINATION, listpost.getNextPageToken());
mListPost.addAll(listpost.getListItemsPost());\
mPostAdapter .notifyDataSetChanged();
}
For nextPageToken thing you can move into your main code onCreate() or the initDataView() method where you already have the adapter initialization
like this,
private void initDataView(ListPostModel listpost){
GlobalFunction.saveString(this,GlobalVariable.keySharedPreference.TOKEN_PAGINATION, listpost.getNextPageToken());
final String nextPageToken = GlobalFunction.getStrings(this, GlobalVariable.keySharedPreference.TOKEN_PAGINATION);
mListPost.addAll(listpost.getListItemsPost());
mPostAdapter = new ListPostAdapter(mListPost, this) {
#Override
public void load() {
ItemPostModel item = mListPost.get(mListPost.size()-1);
if(nextPageToken==null){
}else{
getNextListPost();
}
}
};
mRecyclerviewPost.setAdapter(mPostAdapter);
//mPostAdapter.notifyDataSetChanged();
mRecyclerviewPost.setHasFixedSize(true);
mGridViewLayoutManager = new StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL);
mGridViewLayoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
mRecyclerviewPost.setLayoutManager(mGridViewLayoutManager);
}
I hope it will work :)

How to change android:entries array list in the spinner dynamically in Android

I am working on a android project where I have 2 Custom spinner
State
City
i am using below code to to populate the spinner with Custom list view.
xml code:
<com.infantstudio.CatholicMithrulu.Spinner.SearchableSpinnerState
android:id="#+id/spinner2"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:entries="#array/state"
app:hintTextState="Select"/>
SearchableListDialogState.class
package com.infantstudio.CatholicMithrulu.Spinner;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.SearchManager;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SearchView;
import com.infantstudio.CatholicMithrulu.R;
import java.io.Serializable;
import java.util.List;
public class SearchableListDialogState extends DialogFragment implements
SearchView.OnQueryTextListener, SearchView.OnCloseListener {
private static final String ITEMS = "items";
private ArrayAdapter listAdapter;
private ListView _listViewItems;
private SearchableListDialogState.SearchableItem _searchableItem;
private OnSearchTextChanged _onSearchTextChanged;
private SearchView _searchView;
private String _strTitle;
private String _strPositiveButtonText;
private DialogInterface.OnClickListener _onClickListener;
public SearchableListDialogState() {
}
public static SearchableListDialogState newInstance(List items) {
SearchableListDialogState multiSelectExpandableFragment = new
SearchableListDialogState();
Bundle args = new Bundle();
args.putSerializable(ITEMS, (Serializable) items);
multiSelectExpandableFragment.setArguments(args);
return multiSelectExpandableFragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams
.SOFT_INPUT_STATE_HIDDEN);
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Getting the layout inflater to inflate the view in an alert dialog.
LayoutInflater inflater = LayoutInflater.from(getActivity());
// Crash on orientation change #7
// Change Start
// Description: As the instance was re initializing to null on rotating the device,
// getting the instance from the saved instance
if (null != savedInstanceState) {
_searchableItem = (SearchableItem) savedInstanceState.getSerializable("item");
}
// Change End
View rootView = inflater.inflate(R.layout.searchable_list_dialog, null);
setData(rootView);
AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
alertDialog.setView(rootView);
String strPositiveButton = _strPositiveButtonText == null ? "CLOSE" : _strPositiveButtonText;
alertDialog.setPositiveButton(strPositiveButton, _onClickListener);
String strTitle = _strTitle == null ? "Select Item" : _strTitle;
alertDialog.setTitle(strTitle);
final AlertDialog dialog = alertDialog.create();
dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams
.SOFT_INPUT_STATE_HIDDEN);
return dialog;
}
// Crash on orientation change #7
// Change Start
// Description: Saving the instance of searchable item instance.
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putSerializable("item", _searchableItem);
super.onSaveInstanceState(outState);
}
// Change End
public void setTitle(String strTitle) {
_strTitle = strTitle;
}
public void setPositiveButton(String strPositiveButtonText) {
_strPositiveButtonText = strPositiveButtonText;
}
public void setPositiveButton(String strPositiveButtonText, DialogInterface.OnClickListener onClickListener) {
_strPositiveButtonText = strPositiveButtonText;
_onClickListener = onClickListener;
}
public void setOnSearchableItemClickListener(SearchableItem searchableItem) {
this._searchableItem = searchableItem;
}
public void setOnSearchTextChangedListener(OnSearchTextChanged onSearchTextChanged) {
this._onSearchTextChanged = onSearchTextChanged;
}
private void setData(View rootView) {
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context
.SEARCH_SERVICE);
_searchView = (SearchView) rootView.findViewById(R.id.search);
_searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName
()));
_searchView.setIconifiedByDefault(false);
_searchView.setOnQueryTextListener(this);
_searchView.setOnCloseListener(this);
_searchView.clearFocus();
InputMethodManager mgr = (InputMethodManager) getActivity().getSystemService(Context
.INPUT_METHOD_SERVICE);
mgr.hideSoftInputFromWindow(_searchView.getWindowToken(), 0);
List items = (List) getArguments().getSerializable(ITEMS);
_listViewItems = (ListView) rootView.findViewById(R.id.listItems);
//create the adapter by passing your ArrayList data
listAdapter = new ArrayAdapter(getActivity(), android.R.layout.simple_list_item_1,items);
//attach the adapter to the list
_listViewItems.setAdapter(listAdapter);
_listViewItems.setTextFilterEnabled(true);
_listViewItems.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
_searchableItem.onSearchableItemClicked(listAdapter.getItem(position), position);
getDialog().dismiss();
}
});
}
#Override
public boolean onClose() {
return false;
}
#Override
public boolean onQueryTextSubmit(String s) {
_searchView.clearFocus();
return true;
}
#Override
public boolean onQueryTextChange(String s) {
// listAdapter.filterData(s);
if (TextUtils.isEmpty(s)) {
// _listViewItems.clearTextFilter();
((ArrayAdapter) _listViewItems.getAdapter()).getFilter().filter(null);
} else {
((ArrayAdapter) _listViewItems.getAdapter()).getFilter().filter(s);
}
if (null != _onSearchTextChanged) {
_onSearchTextChanged.onSearchTextChanged(s);
}
return true;
}
public interface SearchableItem<T> extends Serializable {
void onSearchableItemClicked(T item, int position);
}
public interface OnSearchTextChanged {
void onSearchTextChanged(String strText);
}
}
SearchableSpinnerState.class
package com.infantstudio.CatholicMithrulu.Spinner;
import android.app.Activity;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.res.TypedArray;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;
import android.widget.Toast;
import com.infantstudio.CatholicMithrulu.Adddata;
import com.infantstudio.CatholicMithrulu.R;
import java.util.ArrayList;
import java.util.List;
public class SearchableSpinnerState extends Spinner implements View.OnTouchListener,
SearchableListDialogState.SearchableItem {
String selectedItem;
//this string above will store the value of selected item.
public static final int NO_ITEM_SELECTED = -1;
private Context _context;
private List _items;
private SearchableListDialogState _searchableListDialog;
private boolean _isDirty;
private ArrayAdapter _arrayAdapter;
private String _strHintText;
private boolean _isFromInit;
public SearchableSpinnerState(Context context) {
super(context);
this._context = context;
init();
}
public SearchableSpinnerState(Context context, AttributeSet attrs) {
super(context, attrs);
this._context = context;
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SearchableSpinnerState);
final int N = a.getIndexCount();
for (int i = 0; i < N; ++i) {
int attr = a.getIndex(i);
if (attr == R.styleable.SearchableSpinnerState_hintTextState) {
_strHintText = a.getString(attr);
}
}
a.recycle();
init();
}
public SearchableSpinnerState(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this._context = context;
init();
}
private void init() {
_items = new ArrayList();
System.out.println("items"+_items);
_searchableListDialog = SearchableListDialogState.newInstance
(_items);
_searchableListDialog.setOnSearchableItemClickListener(this);
setOnTouchListener(this);
_arrayAdapter = (ArrayAdapter) getAdapter();
if (!TextUtils.isEmpty(_strHintText)) {
ArrayAdapter arrayAdapter = new ArrayAdapter(_context, android.R.layout
.simple_list_item_1, new String[]{_strHintText});
_isFromInit = true;
setAdapter(arrayAdapter);
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if (null != _arrayAdapter) {
// Refresh content #6
// Change Start
// Description: The items were only set initially, not reloading the data in the
// spinner every time it is loaded with items in the adapter.
_items.clear();
for (int i = 0; i < _arrayAdapter.getCount(); i++) {
_items.add(_arrayAdapter.getItem(i));
}
// Change end.
_searchableListDialog.show(scanForActivity(_context).getFragmentManager(), "TAG");
}
}
return true;
}
#Override
public void setAdapter(SpinnerAdapter adapter) {
if (!_isFromInit) {
_arrayAdapter = (ArrayAdapter) adapter;
if (!TextUtils.isEmpty(_strHintText) && !_isDirty) {
ArrayAdapter arrayAdapter = new ArrayAdapter(_context, android.R.layout
.simple_list_item_1, new String[]{_strHintText});
super.setAdapter(arrayAdapter);
} else {
super.setAdapter(adapter);
}
} else {
_isFromInit = false;
super.setAdapter(adapter);
}
}
//The method just below is executed when an item in the searchlist is tapped.This is where we store the value int string called selectedItem.
#Override
public void onSearchableItemClicked(Object item, int position) {
setSelection(_items.indexOf(item));
if (!_isDirty) {
_isDirty = true;
setAdapter(_arrayAdapter);
setSelection(_items.indexOf(item));
}
selectedItem= item.toString().trim();
Adddata.setValueSt(selectedItem);
// Toast.makeText(getContext(),"You selected "+selectedItem, Toast.LENGTH_LONG).show();
}
private Activity scanForActivity(Context cont) {
if (cont == null)
return null;
else if (cont instanceof Activity)
return (Activity) cont;
else if (cont instanceof ContextWrapper)
return scanForActivity(((ContextWrapper) cont).getBaseContext());
return null;
}
#Override
public int getSelectedItemPosition() {
if (!TextUtils.isEmpty(_strHintText) && !_isDirty) {
return NO_ITEM_SELECTED;
} else {
return super.getSelectedItemPosition();
}
}
#Override
public Object getSelectedItem() {
if (!TextUtils.isEmpty(_strHintText) && !_isDirty) {
return null;
} else {
return super.getSelectedItem();
}
}
}
The above code is working fine, but I need to change the array at run time . Array is declared in the xml file like this
android:entries="#array/state"
How can I modify this array at run time? Any help would be valuable.
--Thanks!
Create ArrayList and insert the entries that you are getting from API or add it.
List < String > list = new ArrayList < > ();
list.add("Male");
list.add("Female");
list.add("Others");
ArrayAdapter < String > dataAdapter = new ArrayAdapter < String > (this, android.R.layout.simple_spinner_item, list);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerGender.setAdapter(dataAdapter);
or
List<String> list= new ArrayList<>();
ArrayAdapter<String> dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, list);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerGender.setAdapter(dataAdapter);
onResposeSucessofAPI(List<String> list){
this.list = list;
dataAdapter.notifyDataSetChanged();
}
Create a arrayList of Strings
ArrayList<String> area = new ArrayList<>();
add values in area arrayList
area.add("value1");
area.add("value2");
Now set adapter
yourSpinner.setAdapter(new ArrayAdapter<String>(context
, android.R.layout.simple_list_item_1, area));
Anything declared in Resources, cannot be changed at Runtime
You must do it by java code

RecyclerView does not update or refresh when calling notifyDataSetChanged()

I have an app that uses RecyclerView. When user selects "Add New Row" from the options menu, I output a test message to the screen, and some values get appended to two different ArrayLists. That part is working great, as I have confirmed these values are successfully added by looking at the ArrayList values using the debugger.
Anyhow I am not able to get the RecyclerView to redraw the screen and show the new information. My attempt to redraw / update the screen is by using this code (line 78 of MainActivity.java):
//call notify data set changed method for the adapter
adapter.notifyDataSetChanged();
Maybe I am not calling notifyDataSetChanged on the same adapter that actually is used for RecycleView??
Here is the complete code for MainActivity.java (see options menu code at end):
package com.joshbgold.ironmax;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private static final int ADD_ROW = 1; //used for case statement statement to select menu item
private RecyclerView recyclerView;
public Exercises exercises = new Exercises();
public ExerciseRow adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
assert getSupportActionBar() != null;
ActionBar actionBar = getSupportActionBar();
actionBar.setDisplayShowHomeEnabled(true);
actionBar.setIcon(R.mipmap.barbell);
actionBar.setTitle(" " + "Iron Max");
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
//ExerciseRow adapter = new ExerciseRow(this);
adapter = new ExerciseRow(this);
recyclerView.setAdapter(adapter);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
/* MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.add_row, menu);
return super.onCreateOptionsMenu(menu);*/
menu.add(0, ADD_ROW, 0, "Add New Row");
menu.getItem(0).setIcon(R.drawable.plus);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onPrepareOptionsMenu(Menu menu) {
menu.getItem(0).setIcon(R.drawable.plus);
return super.onPrepareOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int length;
switch (item.getItemId()) {
case 1:
Toast msg = Toast.makeText(MainActivity.this, "Test code for adding an exercise", Toast.LENGTH_LONG);
msg.show();
exercises.addExercise("Some exercise");
exercises.addPersonalBest(500);
length = exercises.getExercisesArrayLength();
//call notify data set changed method for the adapter
adapter.notifyItemInserted(length - 1);
adapter.notifyDataSetChanged();
return super.onOptionsItemSelected(item);
default:
return super.onOptionsItemSelected(item);
}
}
}
Here is Exercises.java:
import android.support.v7.app.AppCompatActivity;
import java.util.ArrayList;
public class Exercises extends AppCompatActivity {
public ArrayList<String> exercisesArrayList = new ArrayList<>(); //stores all the lifts
private ArrayList<Integer> personalBestsArrayList = new ArrayList<>(); //stores personal bests in pounds
public ArrayList<String> getExercisesArray() { //returns the whole exercises arraylist
return exercisesArrayList;
}
public ArrayList<Integer> getPersonalBests() { //returns the whole personal bests arraylist
return personalBestsArrayList;
}
public String getExercise(int position) { //returns individual exercise from array
return exercisesArrayList.get(position);
}
public void addExercise(String exercise) {
exercisesArrayList.add(exercise);
}
public void removeExercise(int position) {
exercisesArrayList.remove(position);
}
public void editExercise(int position, String exercise) {
exercisesArrayList.set(position, exercise);
}
public int getExercisesArrayLength() {
return exercisesArrayList.size();
}
public Integer getPersonalBest(int position) { //returns individual personal best from array
return personalBestsArrayList.get(position);
}
public void addPersonalBest(int personalBest) {
personalBestsArrayList.add(personalBest);
}
public void removePersonalBest(int position) {
personalBestsArrayList.remove(position);
}
public void editPersonalBest(int position, int personalBest) {
personalBestsArrayList.set(position, personalBest);
}
public Exercises() {} //constructor
}
Here is ExerciseRow.java:
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
public class ExerciseRow extends RecyclerView.Adapter<ExerciseRow.ExerciseViewHolder> {
String exerciseName = "burpee";
String exercisePR = "100"; // user's personal record for this exercise in pounds
private Context context;
Exercises exercises = new Exercises();
public ExerciseRow(Context context) {
this.context = context;
}
#Override
public ExerciseViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.exercise_list_item, parent, false);
return new ExerciseViewHolder(view);
}
#Override
public void onBindViewHolder(ExerciseViewHolder holder, int position) {
ArrayList<String> exercisesArray = exercises.getExercisesArray();
holder.bindExercises(exercisesArray.get(position));
}
#Override
public int getItemCount() {
return exercises.getExercisesArrayLength();
}
public class ExerciseViewHolder extends RecyclerView.ViewHolder {
public TextView exerciseNameTextView;
public TextView personalRecordTextView;
public ImageView edit_Icon;
public ImageView percentages_Icon;
public ImageView trash_Icon;
public ImageView plus_icon;
public ImageView facebook_icon;
public ImageView twitter_icon;
public ExerciseViewHolder(View itemView) {
super(itemView);
exerciseNameTextView = (TextView) itemView.findViewById(R.id.list_item_exercise_textview);
personalRecordTextView = (TextView) itemView.findViewById(R.id.list_item_amount_textview);
edit_Icon = (ImageView) itemView.findViewById(R.id.list_item_pencil);
percentages_Icon = (ImageView) itemView.findViewById(R.id.list_item_percent);
trash_Icon = (ImageView) itemView.findViewById(R.id.list_item_trash);
plus_icon = (ImageView) itemView.findViewById(R.id.list_item_plus);
facebook_icon = (ImageView) itemView.findViewById(R.id.list_item_facebook);
twitter_icon = (ImageView) itemView.findViewById(R.id.list_item_twitter);
View.OnClickListener plus = new View.OnClickListener() {
#Override
public void onClick(View view) {
// allow user to add a new exercise and personal best
exercises.addExercise("Some exercise");
exercises.addPersonalBest(500);
notifyDataSetChanged();
}
};
View.OnClickListener edit = new View.OnClickListener() {
#Override
public void onClick(View view) {
int position = getLayoutPosition(); //use getAdapterPosition() if getLayoutPosition causes a problem
if (position == 0) { //prevent user from deleting the first row.
Toast.makeText(context, "Sorry, example row cannot be edited.", Toast.LENGTH_LONG).show();
}
else{
editRow(position); //edit the row at the current position
notifyDataSetChanged();
}
}
};
View.OnClickListener percentages = new View.OnClickListener() {
#Override
public void onClick(View view) {
//get exercise name
exerciseName = exerciseNameTextView.getText().toString();
exercisePR = personalRecordTextView.getText().toString();
//show percentages layout
startPercentagesActivity(exerciseName, exercisePR);
}
};
View.OnClickListener trash = new View.OnClickListener() {
#Override
public void onClick(View view) {
int position = getLayoutPosition(); //use getAdapterPosition() if getLayoutPosition causes a problem
if (position == 0) { //prevent user from deleting the first row.
Toast.makeText(context, "Sorry, example row cannot be deleted.", Toast.LENGTH_LONG).show();
} else {
exercises.removeExercise(position);
exercises.removePersonalBest(position);
notifyItemRemoved(position);
notifyItemRangeChanged(position, exercises.getExercisesArrayLength());
}
}
};
plus_icon.setOnClickListener(plus);
edit_Icon.setOnClickListener(edit);
percentages_Icon.setOnClickListener(percentages);
trash_Icon.setOnClickListener(trash);
}
public void bindExercises(String exercises) {
Exercises exercisesObject = new Exercises();
exerciseNameTextView.setText(exercisesObject.getExercise(getAdapterPosition()));
personalRecordTextView.setText((exercisesObject.getPersonalBest(getAdapterPosition())).toString() + " pounds");
}
}
private void startPercentagesActivity(String some_exercise, String personal_record) {
Intent intent = new Intent(context, PercentagesActivity.class);
intent.putExtra("exerciseName", some_exercise);
intent.putExtra("personalRecord", personal_record);
context.startActivity(intent);
}
protected void editRow(final int position) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
//text_entry is an Layout XML file containing two text field to display in alert dialog
final View textEntryView = layoutInflater.inflate(R.layout.text_entry, null);
final EditText liftName = (EditText) textEntryView.findViewById(R.id.liftNameEditText);
final EditText PersonalBestInPounds = (EditText) textEntryView.findViewById(R.id.personalBestEditText);
final AlertDialog.Builder alert = new AlertDialog.Builder(context);
alert.setIcon(R.mipmap.barbell)
.setTitle("Please make your changes:")
.setView(textEntryView)
.setPositiveButton("Save",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//retrieve the user's input
String lift = liftName.getText().toString();
int personalBest = Integer.parseInt(PersonalBestInPounds.getText().toString());
//save the user's input to the appropriate arrays
exercises.editExercise(position, lift);
exercises.editPersonalBest(position, personalBest);
}
})
.setNegativeButton("Cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
}
});
alert.show();
}
}
If you have read this far, I give you credit! Please understand I am completely new to RecyclerView, so whatever error(s) I have made could be something quite simple even.
The issue is that you have two different instances of ExercisesOne in MainActivity and another in ExerciseRow You are adding the data to the wrong one.
A few other things that may help you along your way.
Exercises Should not extend AppCompatActivity (or really anything as far as I can tell)
You should avoid saving a reference to the context (as you are doing in Exercises) it can great memory issues. Instead try one of the following.
A. Use the context to get the LayoutInflater in the constructor
B. Call parent.getContext() in onCreateViewHolder

Append items to a ListView

I would like to append new items to a ListView to enable endless scrolling.
private ListAdapter adapter;
ArrayList < HashMap < String, String >> listViewList;
...
class GetItems extends AsyncTask < String, String, String > {
protected String doInBackground(String...args) {
...
for (int i = 0; i < items.length(); i++) {
...
HashMap < String, String > map = new HashMap < String, String > ();
map.put("name_1", name_1);
map.put("name_2", name_3);
map.put("name_3", name_3);
listViewList.add(map);
}
}
protected void onPostExecute(String file_url) {
adapter = new CustomAdapter(Activity.this, listViewList,
R.layout.single_item, new String[] {}, new int[] {});
setListAdapter(adapter);
}
}
GetItems class gets new items based on a page number you provide. I would like to append new items to existing ListView items on onPostExecute.
Any idea how to do it?
Check out this library on GitHub
https://github.com/codepath/android_guides/wiki/Endless-Scrolling-with-AdapterViews
EDIT according to your comment:
You need to forget about ListActivity and that you ever heard it exists, it's useless for what you are trying to do.
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class DemosAdapter extends BaseAdapter {
public List<DemoItem> listOfItems;
private View v;
private ViewWrapper wrapper;
private Context context;
public DemosAdapter(Context c, List<DemoItem> listOfItems) {
this.context = c;
this.listOfItems = listOfItems;
}
#Override
public int getCount() {
return listOfItems.size();
}
#Override
public DemoItem getItem(int i) {
return listOfItems.get(i);
}
#Override
public long getItemId(int i) {
return 0;
}
public void sort() {
Collections.sort(listOfItems, new Comparator<DemoItem>() {
#Override
public int compare(DemoItem item, DemoItem item2) {
return item.getName().compareTo(item2.getName());
}
});
}
public void addItems(List<DemoItem> listOfFreshItems){
listOfItems.addAll(listOfFreshItems);
notifyDataSetChanged();
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
DemoItem itm = listOfItems.get(position);
v = convertView;
if (v == null) {
LayoutInflater inflater = LayoutInflater.from(context);
v = inflater.inflate(R.layout.demo_item, null, false);
wrapper = new ViewWrapper(v);
v.setTag(wrapper);
}
else {
wrapper = (ViewWrapper) v.getTag();
}
wrapper.getTvDemoName().setText(itm.getName());
return v;
}
private class ViewWrapper {
private View base;
private TextView tvDemoName;
public ViewWrapper(View v) {
this.base = v;
}
public TextView getTvDemoName() {
if (tvDemoName == null) {
tvDemoName = (TextView) base.findViewById(R.id.tvDemoName);
}
return tvDemoName;
}
}
}
The first time you add data, do this
demosAdapter = new DemosAdapter(this, listOfDemos);
demosAdapter.sort();
lvListOfDemos.setAdapter(demosAdapter);
When you get new items, just call
adapter.addItems(List<DemoItem> newItems);
Actually you just need to call adapter.notifyDataSetChanged in onPostExecute.
But you should not instantiate adapter many times. It should be done just one so overall it would look like this
private ListAdapter adapter;
...
void onCreate(){ // assuming this is an activity
adapter = new CustomAdapter(Activity.this, listViewList,
R.layout.single_item, new String[] {}, new int[] {});
setListAdapter(adapter);
}
class GetItems extends AsyncTask<String, String, String> {
...
protected void onPostExecute(String file_url) {
adapter.notifyDataSetChanged();
}
}

Trying to implement onScrollListener on ListView but keeps freezing towards bottom

Im trying to have my ListView add more items once the bottom of the list has been reached. The problem I keep having is the list freezes once it reaches the bottom instead updating the view. In EndlessScrollListenener, i check if the last item is visible, if it is, we add more posts to our List posts. Then I do a notifyDataSetChanged() but it is not working. Any help?
Here is my custom
EndlessScrollListener class:
import java.util.ArrayList;
import java.util.List;
import sukh.app.ireddit.PostsFragment.PostAdapter;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ArrayAdapter;
public class EndlessScrollListener implements OnScrollListener {
List<Post> posts;
PostsHolder postsHolder;
ArrayAdapter<Post> postAdapter;
private int count, incrementSize;
public EndlessScrollListener() {
}
public EndlessScrollListener(List<Post> posts, PostsHolder postsHolder, ArrayAdapter<Post> adapter){
this.posts = posts;
this.postsHolder = postsHolder;
this.postAdapter = adapter;
count = incrementSize = adapter.getCount();
}
public void onScroll(AbsListView view, int firstVisible, int visibleCount, int totalCount) {
// TODO Auto-generated method stub
boolean loadMore =
firstVisible + visibleCount >= totalCount;
if(loadMore) {
count += incrementSize; // or any other amount
new Thread(){
public void run(){
posts.addAll(postsHolder.fetchMorePosts());
}
}.start();
postAdapter.notifyDataSetChanged();
}
}
#Override
public void onScrollStateChanged(AbsListView arg0, int arg1) {
// TODO Auto-generated method stub
}
}
my PostFragment class
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
/**
* While this looks like a lot of code, all this class
* actually does is load the posts in to the listview.
*/
public class PostsFragment extends Fragment{
ListView postsList;
ArrayAdapter<Post> adapter;
Handler handler;
String subreddit;
List<Post> posts;
PostsHolder postsHolder;
public PostsFragment(){
handler=new Handler();
posts=new ArrayList<Post>();
}
public static Fragment newInstance(String subreddit){
PostsFragment pf=new PostsFragment();
pf.subreddit=subreddit;
pf.postsHolder=new PostsHolder(pf.subreddit);
return pf;
}
#Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.posts
, container
, false);
postsList=(ListView)v.findViewById(R.id.posts_list);
return v;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
initialize();
}
private void initialize(){
// This should run only once for the fragment as the
// setRetainInstance(true) method has been called on
// this fragment
if(posts.size()==0){
// Must execute network tasks outside the UI
// thread. So create a new thread.
new Thread(){
public void run(){
posts.addAll(postsHolder.fetchPosts());
// UI elements should be accessed only in
// the primary thread, so we must use the
// handler here.
handler.post(new Runnable(){
public void run(){
createAdapter();
}
});
}
}.start();
}else{
createAdapter();
}
}
/**
* This method creates the adapter from the list of posts
* , and assigns it to the list.
*/
private void createAdapter(){
// Make sure this fragment is still a part of the activity.
if(getActivity()==null) return;
adapter=new PostAdapter(posts);
postsList.setAdapter(adapter);
postsList.setOnScrollListener(new EndlessScrollListener(posts, postsHolder, adapter));
}
protected class PostAdapter extends ArrayAdapter<Post> {
public int incrementSize
, count = 0;
public PostAdapter(List<Post> posts){
super(getActivity(), R.layout.post_item, posts);
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if(convertView == null){
convertView = getActivity().getLayoutInflater().inflate(R.layout.post_item, null);
}
Post thePost = getItem(position);
TextView postTitleTextView = (TextView) convertView.findViewById(R.id.post_title);
postTitleTextView.setText(thePost.getTitle());
TextView postDetailsTextView = (TextView) convertView.findViewById(R.id.post_details);
postDetailsTextView.setText(thePost.getDetails());
TextView postScoreTextView = (TextView) convertView.findViewById(R.id.post_score);
postScoreTextView.setText(thePost.getScore());
return convertView;
}
}
}
my PostsHolder class:
import java.util.ArrayList;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
import android.util.Log;
/**
* This is the class that creates Post objects out of the Reddit
* API, and maintains a list of these posts for other classes
*/
public class PostsHolder {
/**
* We will be fetching JSON data from the API.
*/
private final String URL_TEMPLATE=
"http://www.reddit.com/r/SUBREDDIT_NAME/"
+".json"
+"?after=AFTER";
String subreddit;
String url;
String after;
PostsHolder(String sr){
subreddit=sr;
after="";
generateURL();
}
/**
* Generates the actual URL from the template based on the
* subreddit name and the 'after' property.
*/
private void generateURL(){
url=URL_TEMPLATE.replace("SUBREDDIT_NAME", subreddit);
url=url.replace("AFTER", after);
}
/**
* Returns a list of Post objects after fetching data from
* Reddit using the JSON API.
*
* #return
*/
ArrayList<Post> fetchPosts(){
String raw=RemoteData.readContents(url);
ArrayList<Post> list=new ArrayList<Post>();
try{
JSONObject data=new JSONObject(raw)
.getJSONObject("data");
JSONArray children=data.getJSONArray("children");
//Using this property we can fetch the next set of
//posts from the same subreddit
after=data.getString("after");
for(int i=0;i<children.length();i++){
JSONObject cur=children.getJSONObject(i)
.getJSONObject("data");
Post p = new Post();
p.title=cur.optString("title");
p.url=cur.optString("url");
p.numComments=cur.optInt("num_comments");
p.points=cur.optInt("score");
p.author=cur.optString("author");
p.subreddit=cur.optString("subreddit");
p.permalink=cur.optString("permalink");
p.domain=cur.optString("domain");
p.id=cur.optString("id");
if(p.title!=null)
list.add(p);
}
}catch(Exception e){
Log.e("fetchPosts()",e.toString());
}
return list;
}
/**
* This is to fetch the next set of posts
* using the 'after' property
* #return
*/
List<Post> fetchMorePosts(){
generateURL();
return fetchPosts();
}
}
You should notify postAdapter.notifyDataSetChanged(); after posts are added. Now Thread runnable could end afterpostAdapter.notifyDataSetChanged().

Categories

Resources