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);
Related
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
I'm using Xamarin Android, and in my app I have a recycle view that gets populated from LiteDB.
Now, in OnCreateView, in my fragment that hold the recycle view, I set the adapters, and call SetData(), to populate my list.
It looks like this:
mLayoutManager = new LinearLayoutManager(Context);
mRecyclerView.SetLayoutManager(mLayoutManager);
mAdapter = new PlaylistItemAdapter(new List<YoutubePlaylistSync>());
mRecyclerView.SetAdapter(mAdapter);
SetData();
This works fine, but when I view the fragment the app freezes. That's normal since the call to fetch the data from the database is blocking.
I wanted to offload the work from the UI thread, so since I need to fire of and forget this function, I replaced my code with:
Task.Run(() => SetData());
This didn't work as I expected, I did confirm that the function is called and the function sets the new data, and calls NotifyNewData().
private void SetData()
{
mAdapter.SetData(db.GetData());
}
//In PlaylistItemAdapter
public void SetData(IEnumerable<YoutubePlaylistSync> newData)
{
playlists.Clear();
foreach (var playlist in newData)
{
playlists.Add(playlist);
}
NotifyDataSetChanged();
}
But the list is not getting populated, if I go to another tab and return, the FAB in my layout disappears, and the drawer is stuck with two items selected (navigation still works).
In addition, if I don't use a task, but a new thread, I get the desired behavior. Like so:
Thread t = new Thread(() =>
{
SetData();
});
t.IsBackground = true;
t.Start();
Note that the app behaves normal, with the first method it works fine.
Why? Is there an alternative way to offload the DB call other than opening another thread? (Its quite an expensive operation)
My implementation of ArrayAdapter is such that it listens for changes in the under lying data. So any changes in the data, the adapter is notified and it calls the notifydataSetChanged()
public class MyAdapter extends ArrayAdapter implements ObjectStateListener {
#Override
public void onObjectStateChanged() {
/*Call appropriate functions as the underlying data as changed.
A good way of doing that would be to retrieve only the positions of the filtered values
so that the original dataholder can be used but display only certain indices
*/
Log.v(TAG, "FilterCriteria changed. Trigger fired");
this.filterPositions = Helper().getFilteredPositions(filterCriteria, mAppartments);
Log.v(TAG, "CALLING NOTIFYDATASETCHANGED()...");
notifyDataSetChanged();
Log.v(TAG, "FINISHED CALLING NOTIFY DATASET CHANGED");
}
}
In the above code the function onObjectStateChanged() is called whenever there is change in the data and in turn it calls notifyDataSetChanged(). To test if the onObjectStateChanged() is called correctly, I have put a bunch of Log statements as you can see. All those logs appear in logcat. But getView() is not getting called after calling notifyDataSetChanged() and hence the listview is not getting refreshed.
Why is this happening? notifyDataSetChanged() is supposed to ensure that getView() gets called and the new data is reflected in the ListView right?
Definition of ObjectStateChangeListener
public interface ObjectStateListener {
public void onObjectStateChanged();
public void listenForStateChange(Object o);
}
If you are deleting or inserting a new value on the list then whenever there is change in adapter list notifystatechange() will be called so just after inserting or deleting the value call notifystatechange () it will refresh the listview.
I've had to stop using notifyDataSetChanged() on my AutoCompleTextViews as they're not refreshing either. I just keep a local copy of the adapter and then reset it with the new dataset when it's changed.
Be sure your ArrayAdapter is set to notify on change (it is by default), and you technically shouldn't even need to make that call to notifyDataSetChanged() based on the docs: http://developer.android.com/reference/android/widget/ArrayAdapter.html
First update the data where you have kept it's reference in the adapter and then call the notifyDataSetChanged(). You will have to pass in the new data as well.
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.