Load more data dynamically in a listview in android - android

i'm doing an android application. I retrive data with GSON and display 10 elements each time i do a request. My problem is that i don't know how to add the new elements, to the elements before, in the bottom of the list. I use onScroll,so when i reach at the end of the list with 10 elements ,i make a request on the server.
I'm trying to integrate some libraries from github ,but it doesn't work.
Here is my code:
First is my method that populate the main list:
public void popullateMainList(final String url,final long expirationTime) {
//requestData(MAIN_LIST_URL);
new AsyncTask<Void, Void, Void>() {
ProgressBar pb = (ProgressBar)findViewById(R.id.progressBar);
#Override
protected void onPreExecute() {
pb.setVisibility(View.VISIBLE);
}
#Override
protected Void doInBackground(Void... voids) {
try {
elements = new Elements(url, expirationTime);
} catch (Exception e) {
e.printStackTrace();
e.printStackTrace();
}
return null;
}
#Override
protected void onPostExecute(final Void result) {
pb.setVisibility(View.GONE);
updateDisplay();
mainElementAdapter.notifyDataSetChanged();
}
}.execute();
}
And the method updateDisplay has the following code:
protected void updateDisplay() {
eList = (ListView) findViewById(R.id.mainView);
mainElementAdapter = new ElementListAdapter(this, elements.getElements());
// mainElementAdapter.add(elements.getElements());
footerView = ((LayoutInflater) this.getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.loading_footer, null, false);
eList.addFooterView(footerView);
eList.setAdapter(mainElementAdapter);
eList.removeFooterView(footerView);
eList.setOnScrollListener(new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == SCROLL_STATE_IDLE) {
if (eList.getLastVisiblePosition() >= eList.getCount() - visibleThreshold) {
currentPage++;
actualUrl = Constants.MAIN_LIST_URL + "?pageNumber=" + currentPage;
popullateMainList(actualUrl,1);
}
}}
public boolean canChildScrollUp() {
//your condition to check scrollview reached at top while scrolling
if (swipeLayout.getScrollY() == 0.0)
return true;
else
return false;
}
#Override
public void onScroll(AbsListView absListView, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
if (firstVisibleItem == 0)
swipeLayout.setEnabled(true);
else
swipeLayout.setEnabled(false);
}
});
}
I hope that anybody help me. Thank you in advance!

Try save old.
when you use
elements = new Elements(url, expirationTime);
you override your Elements object and when you use
mainElementAdapter = new ElementListAdapter(this, elements.getElements());
you override your old data in adapter
added new method in your class Elemets
something like that
if(elements == null) {
elements = new Elements(url, expirationTime);
} else {
elements.add(new Elements(url, expirationTime).getElements());
}

Related

Android ListView with Pull to Refresh & Load more - that is not deprecated!(?)

I am trying to find a good ListView that supports "Pull to Refresh" and "Load more" that works with gradle, works with a bit older APIs ( I currently use the "LoadMoreListView" that requires min API18) and is NOT deprecated...all I can find are depreacted libraries that noone cares about anymore... Any suggestions?
AbsListView.OnScrollListener listenerScroll = new AbsListView.OnScrollListener() {
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
Log.d("TAG", "onScrollStateChanged");
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
boolean loadMore = firstVisibleItem + visibleItemCount >= totalItemCount;
Log.d("TAG", "onScroll " + loadMore + " " + totalItemCount + " ");
if (loadMore && !mIsLoading && !isLoadFinish) {
if (mTrackDataValues != null && mTrackDataValues.size() > 0) {
callAPIHistory(mTrackDataValues.get(mTrackDataValues.size() - 1).getDateFor());
}
}
}
};
You can modify this code to suit your requirement. This class makes use of SwipeRefreshLayout
public class MainActivity extends AppCompatActivity implements SwipeRefreshLayout.OnRefreshListener{
private ListView mListView;
private SwipeRefreshLayout mSwipeRefreshLayout;
private List<String> mObjectList;
private StringAdapter mStringAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mObjectList = new ArrayList<String>();
mObjectList.add("Sweden");
mObjectList.add("Denmark");
mObjectList.add("Finland");
mObjectList.add("Norway");
mObjectList.add("Iceland");
mListView = (ListView)findViewById(R.id.listView);
mSwipeRefreshLayout = (SwipeRefreshLayout)findViewById(R.id.swipe_refresh_layout);
mStringAdapter = new StringAdapter(MainActivity.this, mObjectList);
mListView.setAdapter(mStringAdapter);
mSwipeRefreshLayout.setOnRefreshListener(this);
mSwipeRefreshLayout.setDistanceToTriggerSync(30);
mSwipeRefreshLayout.setSize(SwipeRefreshLayout.DEFAULT);
}
Handler mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
//super.handleMessage(msg);
// add new data source to the adapter
mStringAdapter = new StringAdapter(MainActivity.this, mObjectList);
mListView.setAdapter(mStringAdapter);
mSwipeRefreshLayout.postDelayed(new Runnable() {
#Override
public void run() {
mSwipeRefreshLayout.setRefreshing(false);
}
}, 1000);
}
};
#Override
public void onRefresh() {
mSwipeRefreshLayout.postDelayed(new Runnable() {
#Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
mHandler.sendEmptyMessage(0);
}
}, 1000);
}
}

Listview does not automatically refresh after getting list data from DataStore

I have a ListView which I populate with data from DataStore or from my local database.
I am checking some condition that will determine whether I will fetch data from the DataStore or database. When I fetch from the database the ListView automatically refreshes itself, but when I fetch from the DataStore it does not. I then have to click my TextView, which is below ListView, and when I click it the soft keyboard appears and then my ListView is populated with data from DataStore.
My activity that has the ListView:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_xyz);
list_View = (ListView) findViewById(R.id.data_listView);
list_View.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
list_View.setMultiChoiceModeListener(new Selector());
adapter = new MyAdapter(context,Long.valueOf(id),isOnline());
list_View.setAdapter(adapter);
list_View.setSelection(adapter.getCount() - 1);
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
list_View.setSelection(adapter.getCount() - 1);
}
LoadDataTask ldt = new LoadDataTask();
ldt.execute("123456789");
}
private void loadDataFromDataStore(final Long contactId){
final ArrayList<Data> data = new ArrayList<>();;
d("loadingdataFromDatasore");
GetDataTask task = new GetDataTask(new ApiTask.ResultListener() {
#Override
public void successHook(Object o) {
if (o instanceof GetDataResponse) {
GetDataResponse res = (GetDataResponse) o;
if (res.getData() != null && res.getData().getItems() != null) {
for (ListDataItem i : res.getData().getItems()) {
Data dp = new Data(i.getPosition(), i.getMessage(), i.getDateCreated(),i.getMessageId(),1);
adapter.addFromOtherThread(dp);
}
}
d("Messages loaded from server: " + adapter.getCount());
}
}
}
public class LoadDataTask extends AsyncTask<String,String,Void> {
#Override
protected Void doInBackground(String... params){
if(isOnline && isFirstTime){
loadDataFromDataStore(Long.valueOf(params[0]));
}else{
//load from database
}
return null;
}
#Override
protected void onPostExecute(Void v){
adapter.notifyDataSetChanged();
}
}
My adapter class that extends BaseAdapter (I have removed unnecessary code for this question):
public class DataAdapter extends BaseAdapter {
private ArrayList<Data>data_list;
public DataAdapter(){
data_list = new ArrayList<>();
}
public void addFromOtherThread(Data object) {
data_list.add(object);
}
What am I missing that is making listview not to automatically refresh itself even after calling notifyDatasetChanged()?
change :
#Override
protected void onPostExecute(Void v){
adapter.notifyDataSetChanged();
}
}
to:
#Override
protected void onPostExecute(Void v){
adapter.notifyDataSetChanged();
list_View.setAdapter(adapter);
}
}
Let me know if more clarification is required by commenting below.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_xyz);
list_View = (ListView) findViewById(R.id.data_listView);
list_View.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
list_View.setMultiChoiceModeListener(new Selector());
adapter = new MyAdapter(context,Long.valueOf(id),isOnline());
list_View.setAdapter(adapter);
list_View.setSelection(adapter.getCount() - 1);
adapter.registerDataSetObserver(new DataSetObserver() {
#Override
public void onChanged() {
super.onChanged();
list_View.setSelection(adapter.getCount() - 1);
}
loadDataFromDataStore("123456789")
}
private void loadDataFromDataStore(final Long contactId){
final ArrayList<Data> data = new ArrayList<>();;
d("loadingdataFromDatasore");
new GetDataTask(new ApiTask.ResultListener() {
#Override
public void successHook(Object o) {
if (o instanceof GetDataResponse) {
GetDataResponse res = (GetDataResponse) o;
if (res.getData() != null && res.getData().getItems() != null) {
for (ListDataItem i : res.getData().getItems()) {
Data dp = new Data(i.getPosition(), i.getMessage(), i.getDateCreated(),i.getMessageId(),1);
adapter.addFromOtherThread(dp);
}
}
d("Messages loaded from server: " + adapter.getCount());
adapter.notifyDatasetChanges();
}
}
}.execute();
}
GetDataTask should work on background internally you don't need to starts a AsyncTask from here.
If you want to use AsyncTask then your AsyncTask should wait for the result from GetDataTask which it is not doing in your code implementation.
I don't know which kind of framework you are using to making api call but your implementation seems to look wrong.
I have write the code on assumption bases if your GetDataTask is a AsyncTask or some background processor it will work perfectly.

Async call adapter show nothing

I have a problem.
I´m set an adapter when a asyctask end.
All code rules but when the code is inflated the screen keep white. The code dont throw any exception and i put some log to control execution flow. All is ok but the screen keep white.
I´m doing that:
protected class ObtenerCursos extends AsyncTask<Void, Void, Boolean> {
private JSONArray resultado;
private ProgressDialog dialog;
private Activity_Mis_Curso activity;
List <Curso> lista;
public ObtenerCursos(Activity_Mis_Curso misCursos){
this.activity=misCursos;
}
#Override
protected Boolean doInBackground(Void... params) {
resultado = getCursos(url,usuario);
if (resultado != null) {
lista=parseJSONDocumentos(resultado);
return true;
} else {
return false;
}
}
protected void onPreExecute() {
dialog = ProgressDialog.show(Activity_Mis_Curso.this,
"Obteniendo cursos", "Espere por favor...", true);
}
protected void onPostExecute(Boolean result) {
dialog.cancel();
if (result) {
gridView = (GridView) findViewById(R.id.miscursos_Grid);
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
gridView.setNumColumns(3);
numColumns = 3;
} else {
numColumns = 2;
gridView.setNumColumns(2);
}
gridView.setAdapter(new MisCursosAdapter(Activity_Mis_Curso.this, listaCursos, numColumns));
gridView.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
if (listaCursos.get(position).getSoloReproduccion() == 0) {
Intent i = new Intent(Activity_Mis_Curso.this,
Activity_Main_Tradicional.class);
i.putExtra("Curso", listaCursos.get(position));
finish();
startActivity(i);
} else {
Intent i = new Intent(Activity_Mis_Curso.this,
Activity_Curso_SoloReproductor.class);
i.putExtra("Curso", listaCursos.get(position));
finish();
startActivity(i);
}
}
});
Log.e("ando", "por aqui \n\n");
} else {
Toast.makeText(getBaseContext(), "No se han encontrado cursos",
Toast.LENGTH_LONG).show();
Intent in = new Intent(Activity_Mis_Curso.this,
Activity_Index.class);
finish();
startActivity(in);
}
}
}
I can´t find where is my problem, i don´t know what i´m doing bad.

ListView - Fast scroll bar not visible for first time in 4.4 Kitkat

I have one list view with fast scrolling enabled. For first time, the fast scroll bar is not visible. But if I navigate to another screen and comes back to this, then it's getting visible. This issue is observed with latest Android OS version. i.e., on 4.4 - Kitkat
First vist
Second visit
Any idea on why it's happening like this?
I have same problem. I use solution:
gridView.setFastScrollEnabled(true);
if (Build.VERSION.SDK_INT >= 19) {
gridView.setOnScrollListener(new OnScrollListener() {
private static final int DELAY = 2000;
private AbsListView view;
#Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState != SCROLL_STATE_IDLE) {
view.setFastScrollAlwaysVisible(true);
handler.removeCallbacks(runnable);
}
else {
this.view = view;
handler.postDelayed(runnable, DELAY);
}
}
#Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
private Handler handler = new Handler();
private Runnable runnable = new Runnable() {
#Override
public void run() {
view.setFastScrollAlwaysVisible(false);
view = null;
}
};
});
}
What worked for me was to delay the call on setFastScrollEnabled().
if (Build.VERSION.SDK_INT >= 19) {
mListView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onGlobalLayout() {
mListView.setFastScrollEnabled(true);
if (Build.VERSION.SDK_INT >= 16) {
mListView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
} else {
mListView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
}
});
} else {
mListView.setFastScrollEnabled(true);
}
It's a know issue (reported here and here).
Here's a workaround:
public static void setFastScrolledEnabled(final AdapterView<?> adapterView,final boolean enable)
{
final GridView gridView;
final ListView listView;
if(adapterView instanceof GridView)
{
gridView=(GridView)adapterView;
listView=null;
}
else if(adapterView instanceof ListView)
{
listView=(ListView)adapterView;
gridView=null;
}
else throw new UnsupportedOperationException("setFastScrolledEnabled is only available for gridView/listView");
if(Build.VERSION.SDK_INT==VERSION_CODES.KITKAT)
adapterView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener()
{
#TargetApi(Build.VERSION_CODES.JELLY_BEAN)
#Override
public void onGlobalLayout()
{
if(gridView!=null)
gridView.setFastScrollEnabled(enable);
else if(listView!=null)
listView.setFastScrollEnabled(enable);
adapterView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
else if(gridView!=null)
gridView.setFastScrollEnabled(enable);
else if(listView!=null)
listView.setFastScrollEnabled(enable);
}

Android: PullToRefresh ListView not showing

I have used Chris Banes implementation of pull to refresh list view for my app. The problem is if I set visibility for list view as gone or invisible and make it visible in java code, the list doesn't shows up. On the other hand, if I set its visibility as visible or don't set its visibility, every thing works fine. My requirement is such that I have two list views in the same activity. I have to set the visibility as one will appear first once it get data from server. The other will appear on search function. I had set the visibility for search result's listview as gone in the xml code, and making it visible only once it gets search results. Despite using setVisibility() for this listview, it never shows up screen. I had checked server response as well. It is showing search result on logcat.
I am posting my code below:
Code Snippet from Activity
//The result from this async task will populate the first list view
if(NetworkConnection.isOnline(MainCategory.this))
{
new MainMenuAsyncTask(dataUrl, MainCategory.this, listMainMenu, false).execute();
}
else
{
Log.v(TAG, "no network available");
SeattleNightLifeUtility.OpenWiFiDialog(MainCategory.this, getResources().getString(R.string.no_internet_msg));
}
loadListView();
//This will populate the list view that I have created for search results
_txtAutoSearch.setOnEditorActionListener(new TextView.OnEditorActionListener()
{
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
{
String term = _txtAutoSearch.getText().toString().trim();
if(! term.equals(""))
{
SeattleNightLifeUtility.hideSoftKeyboard(MainCategory.this, _txtAutoSearch);
if(NetworkConnection.isOnline(MainCategory.this))
{
search(term, false);
}
else
{
SeattleNightLifeUtility.OpenWiFiDialog(MainCategory.this, getResources().getString(R.string.no_internet_msg));
}
}
return true;
}//onEditorAction
});
listMainMenu.setOnRefreshListener(new PullToRefreshListView.OnRefreshListener()
{
#Override
public void onRefresh()
{
if(NetworkConnection.isOnline(MainCategory.this))
{
new MainMenuAsyncTask(dataUrl, MainCategory.this, listMainMenu, true).execute();
}
else
{
SeattleNightLifeUtility.OpenWiFiDialog(MainCategory.this, getResources().getString(R.string.no_internet_msg));
}
}
});
listViewSearch.setOnRefreshListener(new PullToRefreshListView.OnRefreshListener()
{
public void onRefresh()
{
if(NetworkConnection.isOnline(MainCategory.this))
{
search(_txtAutoSearch.getText().toString().trim(), true);
}
else
{
SeattleNightLifeUtility.OpenWiFiDialog(MainCategory.this, getResources().getString(R.string.no_internet_msg));
}
}
});
Search result Async Task
public class GetSearchAsyncTask extends AsyncTask<Void, Void, String>
{
Context ctx;
ProgressDialog pd;
PullToRefreshListView listViewSearch;
public static final String TAG = "GetSearchAsyncTask";
public static ArrayList<SearchDAO> searchArrayList;
private String term, callingclass;
private TextView txtNoData;
boolean flag;
public GetSearchAsyncTask(String term, Context ctx,
PullToRefreshListView listViewSearch, TextView txtNoData,
String callingclass, boolean flag)
{
this.term = term;
this.ctx = ctx;
this.listViewSearch = listViewSearch;
this.txtNoData = txtNoData;
this.callingclass = callingclass;
this.flag = flag;
}//Constructor
#Override
protected void onPreExecute()
{
if(flag == false)
{
pd = new ProgressDialog(ctx);
pd.setMessage(ctx.getResources().getString(R.string.please_wait));
pd.show();
}
}//onPreExecute
protected String doInBackground(Void... params)
{
String parsed = ServerConnection.getSearchedData(term);
try
{
if(flag == true)
{
Log.v(TAG, "doInBackground isListRefreshed is true");
Thread.sleep(2000);
}
}
catch(Exception e){}
return parsed;
}//doInBackground
#Override
protected void onPostExecute(String result)
{
searchArrayList = ParsedSearchData.getSearchedData(result);
listViewSearch.setVisibility(View.VISIBLE);
if(searchArrayList != null && searchArrayList.size() > 0)
{
Log.v(TAG, "searcharraylist not null");
for(int i = 0; i < searchArrayList.size(); i++)
{
Log.v(TAG, "Name: "+searchArrayList.get(i).getMerchant());
}
SearchAdapter mSearchAdapter = new SearchAdapter(ctx, searchArrayList);
mSearchAdapter.notifyDataSetChanged();
listViewSearch.setAdapter(mSearchAdapter);
if(callingclass.equals("EventActivity"))
{
Log.v(TAG, "callingclass EventActivity");
if(txtNoData.getVisibility() == View.VISIBLE)
{
Log.v(TAG, "txtNoData VISIBLE");
txtNoData.setVisibility(View.GONE);
}
if(((EventsActivity)ctx).txtNoEvent.getVisibility() == View.VISIBLE)
{
Log.v(TAG, "txtNoEvent VISIBLE");
((EventsActivity)ctx).txtNoEvent.setVisibility(View.GONE);
}
}
else
{
Log.v(TAG, "callingclass not EventActivity");
if(txtNoData.getVisibility() == View.VISIBLE)
{
Log.v(TAG, "else loop txtNoData VISIBLE");
txtNoData.setVisibility(View.GONE);
}
if(listViewSearch.getVisibility() == View.VISIBLE)
{
Log.v(TAG, "listViewSearch VISIBLE");
}
else
{
Log.v(TAG, "listViewSearch INVISIBLE");
}
}
}
else
{
Log.v(TAG, "searcharraylist null");
if(callingclass.equals("EventActivity"))
{
Log.v(TAG, "callingclass EventActivity");
txtNoData.setVisibility(View.VISIBLE);
listViewSearch.setVisibility(View.GONE);
if(((EventsActivity)ctx).txtNoEvent.getVisibility() == View.VISIBLE)
{
Log.v(TAG, "searcharraylist null else txtNoEvent VISIBLE");
((EventsActivity)ctx).txtNoEvent.setVisibility(View.GONE);
}
}
else
{
Log.v(TAG, "callingclass not EventActivitysearcharraylist null else txtNoEvent VISIBLE");
txtNoData.setVisibility(View.VISIBLE);
listViewSearch.setVisibility(View.GONE);
}
}
if(flag == false)
{
if(pd != null)
{
Log.v(TAG, "onPostExecute pd not null");
if(pd.isShowing())
{
Log.v(TAG, "onPostExecute pd is showing");
pd.dismiss();
}
}
}
else
{
listViewSearch.onRefreshComplete();
}
}//onPostExecute
}
Search Method
protected void search(String term, boolean result)
{
listMainMenu.setVisibility(View.GONE);
//listViewSearch.setVisibility(View.VISIBLE);
new GetSearchAsyncTask(term, MainCategory.this, listViewSearch , txtNoData, "MainCategory", result).execute();
}//search
Earlier I was setting visibility of in the XML as gone and in java code, I was making it VISIBLE. At that time, the list didn't showed up. When I removed the visibility attribute from XML layout file, and only set it in java code with setVisibility(), it worked perfect. I couldn't figured out the reason behind this. May be, I need to take a look at the implementation of library so that I find where did I went wrong. But, for the time being, this is what worked for me.

Categories

Resources