I have displayed some data in a Listview using ListAdapter. Now I want the listview to refresh automatically after x seconds. How can this be done?
I am using AsyncTask to fetch data from Server.
I have tried this:
public void reloadDeviceData() {
handler.postDelayed(runnable = new Runnable() {
public void run() {
new GetDevices().execute(); // this method will contain your almost-finished HTTP calls
handler.postDelayed(this, TIME);
}
}, TIME);
}
What is happening is that the listview does not refresh but instead add items after the current listview.
GetDevices is the class which extends AsyncTask here.
When you get the response from API. just update the adapter list by using follwing line adapter.list.clear() then after adapter.list.addAll(apiList) and then after You just have to notify the listview adapter.
adapter.notifydatasetchanged();
I would recommend :
use recyclerview for performance point of view .
Check Delta difference between new and old list and add /update those items only. For difference you can use either basic collections class methods or DiffUittls lib
Related
I have a simple implementation of RecyclerView with an adapter inside the onResponse method of network call. How can I remove all previous RecyclerView items or refresh RecyclerView?
I have used adapter.notifyDataSetChanged(); and recyclerView.invalidate(); but none of them worked.
I will suggest you use a different approach
use asynchronous method
use variable which array of object, save data you get from network call in that variable
each you call a new request, clear the variable, add data from network call in that variable and refresh the recyclerView
Create a new instance of your adapter and then call recyclerview.setAdapter(newAdapter);
This will remove your old adapter and set the new adapter with the updated items.
If you just want to update the items in the current adapter then create a method inside your adapter to do so:
public void addItems(ArrayList<EventObject> eventList) {
this.eventList.addAll(eventList);
notifyDataSetChanged();
}
And then call adapter.addItems(moreItems);
You need to clear your list before calling notifyDataSetChanged().
Use the following line of code
adapter.clearData();
Don't forget to add this method
public void clearData() {
int size = this.myList.size();
this.myList.clear();
this.notifyItemRangeRemoved(0, size);
}
}
Create your adapter once, outside your OnResponse method. Inside your adapter, have a method for setting the items like:
public void setItems(ArrayList<MyObject> items){
this.items = items;
notifyDataSetChanged();
}
Then in your onResponse method you can call adapter.setItems(items);
Following Steps will help you
After successfully receive response, clear your data set using .clear() method.
Add Newly received data to the model.
Notify the adapter.
Suggestion-
Don't instantiate your adapter, each time after receiving the data.
Use a public method inside your adapter to do this operation also adding the data.
I want to populate a listView with data retrieved from DB asynchronously,
the problem Is that if I set the adapter, it throws null pointer because the data not arrieved yet, when I recieve data one method is executed, so what I can call in this method to populate my listview? I tried passing the layout to this class to populate directly the listview when the data is recieved but don't worked (nothing happened)
I thought using AsyncTask was a good idea adding wait() and when this "retriever data method" is triggered call notify() but I don't know how to call notify() from an asynctask from another class...
I'm also not sure if asynktask is the best way of doing this, any ideas?
I'm using retrofit2 if it helps
Code of listview create/populate
private List<TmOfsDTO> prepareList() {
List<TmOfsDTO> list;
try {
// Create list of items
ListObtainer listObtainer = new ListObtainer(this);
list = listObtainer.getTmOfsDTOList(user); // this method returns list of objects from DB
} catch (Exception e) {
list = null;
e.printStackTrace();
}
return list;
}
private void populateListView(List<TmOfsDTO> lista) {
// Build Adapter
OrderAdapter orderAdapter = new OrderAdapter(this, 0, lista);
// orderAdapter.getView()
Log.d("LSO", ".....");
// Configure listview
//View rootView = View.inflate(this, R.layout.activity_ordenes, null);
ListView listView = (ListView) findViewById(R.id.lvOrdenes);
listView.setAdapter(orderAdapter);
//listView.invalidateViews();
//listView.refreshDrawableState();
Log.d("LSO", ".......");
Last update:
**
I was doing right the notify when I was recieving data, passing the adapter to the class and calling:
orderAdapter.notifyDataSetChanged();
but the problem is I was missing to add each item with:
orderAdapter.add(orden);
before notify, now seem to work good**
As you logcat show above the lista is null. You are passing this list to the adapter. But if you have not initialized the variable lista it will throw a null pointer exception.
Suggest to initialize the List you passing to the adapter. Then when the data comes in you add the data lista and call the method adapter.notifyDataSetChanged()
Following seems to cause the null pointer exception
} catch (Exception e) {
list = null;
e.printStackTrace();
}
So beside initializing you should also not assign null.
You'd be best using a RecyclerView, anyway. This is part of the new support libraries and is way more efficient than the older ListView.
Some key questions here are whether or not the database is local. If your have an sqlite3 database on the phone that you're loading from then you should have written some classes that load the database information into objects that you can store into an array and pass into the RecyclerView.Adapter very easily.
If you are loading this remotely, then you would be 100% better off syncing the data onto your phone using an AsyncTask before trying to load the RecyclerView, otherwise you'll get those errors.
You could load ONE item into an ArrayList from a remote database, pass that to the RecyclerView, and then carry on loading from the remote database and notifying the RecyclerView of a change upon each item being added to the list.
Create a different constructor for your adapter, one that does not receive data to display in it. When you have that, it will not crash.
To get your data inside, create a local List of your items and populate it with something like:
public void setData(List<MyObject> data){
this.mData = data;
notifyDataSetChanged();
}
Also, don't forget to handle possible null pointer errors in methods such as getItem.
lets say we are in viewDidLoad method. I'd suggest you to do the following:
in your adapter class create public method: setData, which calls adapter.notifyDataSetChanged()
send request to backend by passing callback function
display loading/progress dialog
initialize adapter by passing empty array(not null)
when callback is fired and you get the list call adapter's setData and hide the progress dialog.
If you are using Fragments just call setAdapter() another time after data extraction
Ok, so ive spend two days on this and I have tried everything under the sun and Google :L
Basically, if I add or delete something from my server, I want to update my listview which is in mylistfragment from my detailfragment to reflect the changes on the server. The changes have occur ed through clicking either a delete or add button in my detail fragment.
I have a callback method which has everything that I need to repopulate the listview with I just cant seem to get the listview to update.
Any help would be much appreciated.
My callback code is as follows :
public final Handler myCallBackAll = new Handler() {
#Override
public void handleMessage(Message msg) {
ListView lv = (ListView) view.findViewById(R.id.listView1);
if (msg.obj == "No Response") {
TextView tv2 = (TextView) view.findViewById(R.id.textView2);
tv2.setText("No Response. Please check your internet connection");
tv2.setVisibility(View.VISIBLE);
lv.setVisibility(View.INVISIBLE);
} else {
Beer beers = new Beer();
ArrayAdapter<Beer> arrayAdapter = new ArrayAdapter<Beer>(
getActivity(), android.R.layout.simple_list_item_1,(List)msg.obj);
lv.setAdapter(arrayAdapterNew);
arrayAdapter.notifyDataSetChanged();
}
}
};
It doesnt throw any errors just doesnt work
How my callback is called is here
if (isBound) {
myBinder.getAllBeer(myCallBackAll);
}
Its a bounded service I have to use, a stipulation of the project. All this code works, just mylistview wont update
You say that you have already have the callback set up, so I am assuming the callback is being fired accordingly. If that is the case, make sure you update the data source (Array, List, etc) you are using in your adapter to reflect the changes you made in detailfragment.
Also, don't forget that every time you add, edit, delete data from your adapter's data source, you must call mAdapter.notifyDataSetChanged() to tell the adapter something in your data changed.
EDIT
Try creating your handler this way instead: public final Handler myCallBackAll = new Handler(Looper.getMainLooper())
notifyDataSetChanged() must be executed on the main UI thread. When you create a new handler it will execute on its own thread, so you need to make sure it does execute on the UI thread. Take a look at here for more information
finally figured it out, may not be the best approach but it does work, i had declare my listview as a static variable in my main activity, i then reference this variable in both fragments and it works a treat :P
I am working on tabHost with 4 tabwidget, my all four tab widget has a listActivity that shows list of items from different arraylist objects set from Json parsing Bean classes..
Now the application is working f9 but,,, about 5 in 1 time ratio it shows exception that my adapter is reset but listView unable to display data as the adapter is set from background thread.
I can't provide the adapter data from same UI thread b'coz my Bean classes and Data manager are defined else where....
I have used adapter.notifyDataSetChanged() where required...
Please do not suggest that...
With Regards,
Arpit
Even if things are defined some place else you should still be able to set the adapter using:
runOnUiThread(new Runnable() {
#Override
public void run() {
list.setAdapter(adapter);
}
});
or simply post a runnable to the UI thread:
view.post(new Runnable() {
#Override
public void run() {
list.setAdapter(adapter);
}
});
Hope this helps, Christoffer
I'd recommend using a Handler (http://developer.android.com/reference/android/os/Handler.html) to perform all changes to the adapter: create a Handler instance for each Activity and then send a Message (http://developer.android.com/reference/android/os/Message.html) to that handler from your data manager/bean classes with the new data for the list adapter. You can then update the adapter safely from the Handler as it will perform its work on the UI thread.
Short writeup is here: http://www.tutorialforandroid.com/2009/01/using-handler-in-android.html and there are a number of other questions on SO that describe it.
I am trying to add running tasks to the ListView.
When i am adding first time using function called loadTasks(). it's added perfectly.
But when i am trying to reload it, as i am refreshing the task list after every 10 seconds, its adding two or more empty items in my list.
try this code for reload the list
private Handler meethandler=new Handler()
{
public void handleMessage(Message msg) {
ArrayAdapter aa=new ArrayAdapter<String>(HomeScreen.this,android.R.layout.test_list_item, mMeeting);
mMeetinglist.setAdapter(aa);
aa.notifyDataSetChanged();
mMeetinglist.invalidate();
}
};
when you want update the list call the handler like this
meethandler.sendemptymessage(0);