update listview dynamically with adapter - android

This tutorial uses a SimpleAdapter which works fine, but I need to update the arrays in the adapter when new data is entered.
Could you please guide me on how to update a ListView using something other than a SimpleAdapter?

Use a ArrayAdapter backed by an ArrayList. To change the data, just update the data in the list and call adapter.notifyDataSetChanged().

If you create your own adapter, there is one notable abstract function:
public void registerDataSetObserver(DataSetObserver observer) {
...
}
You can use the given observers to notify the system to update:
private ArrayList<DataSetObserver> observers = new ArrayList<DataSetObserver>();
public void registerDataSetObserver(DataSetObserver observer) {
observers.add(observer);
}
public void notifyDataSetChanged(){
for (DataSetObserver observer: observers) {
observer.onChanged();
}
}
Though aren't you glad there are things like the SimpleAdapter and ArrayAdapter and you don't have to do all that?

SimpleListAdapter's are primarily used for static data! If you want to handle dynamic data, you're better off working with an ArrayAdapter, ListAdapter or with a CursorAdapter if your data is coming in from the database.
Here's a useful tutorial in understanding binding data in a ListAdapter
As referenced in this SO question

Most people recommend using notifyDataSetChanged(), but I found this link pretty useful. In fact using clear and add you can accomplish the same goal using less memory footprint, and more responsibe app.
For example:
notesListAdapter.clear();
notes = new ArrayList<Note>();
notesListAdapter.add(todayNote);
if (birthdayNote != null) notesListAdapter.add(birthdayNote);
/* no need to refresh, let the adaptor do its job */

I created a method just for that. I use it any time I need to manually update a ListView. Hopefully this gives you an idea of how to implement your own
public static void UpdateListView(List<SomeObject> SomeObjects, ListView ListVw)
{
if(ListVw != null)
{
final YourAdapter adapter = (YourAdapter) ListVw.getAdapter();
//You'll have to create this method in your adapter class. It's a simple setter.
adapter.SetList(SomeObjects);
adapter.notifyDataSetChanged();
}
}
I'm using an adapter that inherites from BaseAdapter. Should work for any other type of adapter.

Related

How to give RecyclerView Adapter new data from AsyncTaskLoader

My AsyncTaskLoader is loading data from a remote server. When new data arrives, naturally a call is made to onLoadFinished. At this point I don't know how to give the new data to the RecyclerView.Adapter. Calling notifyDataSetChanged does not give it the new data: it simply tells it there is new data. So any advice on how I might do this? Right now the best I can think of is to create my own setData method in my implementation of RecyclerView.Adapter as
public void setData(List<MyObject> data){
if(null != data && !data.isEmpty()){
synchronized(mItems){
mItems.clear();
mItems.addAll(data);
}
notifyDataSetChanged();
}
}
Is my idea the best there is? Or is there a more sound way of doing this?
Expose a public method in your adapter to update data.
For example, you could put it like this
public void updateItems(ArrayList<MyObject> myObjects) {
this.data = myObjects;
notifyDataSetChanged();
}
You have two options,
1. Re- instantiate your adapter with your new data and reset the adapter.
2. The way you do it.
I can not think of any other methods.
Ok, I had the same issue and here is the solution what I did.
1st I passed list object from onLoadFinished and in the RecyclerViewAdapter I have created method name setCardInfoList() and there I passed this object to global List object which I define in adapter class.
In onLoadFinished method..
#Override
public void onLoadFinished(android.content.Loader<List<Earthquake>> loader, List<Earthquake> earthquakes) {
if (earthquakes != null && !earthquakes.isEmpty()) {
adapter.setCardInfoList(earthquakes);
adapter.notifyDataSetChanged();
}else {
emptyView.setText("No Earthquake Found...");
}
}
Inside Adapter class
public void setCardInfoList(List<Earthquake> earthquakes){
this.earthquakeList = earthquakes;
}

notifyDataSetChanged() not showing up for custom list adapter

I have a custom array adapter than extends ArrayAdapter, but the notifyDataSetChanged() method just plain doesn't show up(and does not work if you try it).
class matchAdapter extends ArrayAdapter<Match> {
public matchAdapter(Context context, List<Match> matches) {
super(context, R.layout.match_layout, matches);
}
#Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged();
}
The above is from my adapter class. Would notifyAll() do the same thing?
Your listAdapter is declared as having the type ListAdapter, which doesn't have the method you expect (notifyDataSetChanged). You need to make it at least BaseAdapter or cast it to a BaseAdapter(I am assuming your MatchAdapter is at least a BaseAdapter - if not, well, calling such a method would make no sense:-) )
((BaseAdapter)listAdapter).notifyDataSetChanged();
I'll write an example, it's not a real code but it's how you have to do this.
Create your List
ArrayList<matchList> matchList = new ArrayList<matchList>();
Create an Adapter
adapter = new matchAdapter(this, matchList);
Set the Adapter
YourListView.setAdapter(adapter);
You change the stuff on your List
matchList.add(Stuff for your list);
Notify now that List has changed doing :
adapter.notifyDataSetChanged();
Hope it helps to you, if it does not, just type a comment and I'll try to update my answer.
Edit
I'll give you some examples...
When you want to call notifyDataSetChanged() just do this :
List.clear();
List.addAll(YourStuff);
adapter.notifyDataSetChanged();
Other method could be, you are using an AsyncTask so your onBackGround() you could make it returns items for your list, then on your onPostExecute update the adapter.
Example :
#Override
protected List<matchList> doInBackground(String... params) {
List<matchList> items = loadUpdatedDataset(params);
return items;
}
#Override
protected void onPostExecute(List<matchList> itemschangeds) {
updateAdapterDataset(itemschangeds);
adapter.notifyDataSetChanged();
}
Have you tried compiling and running the app? If there are any syntax errors above your matchAdapter (like a missing ; or "), it'll screw the autocompletion up.

Notifying adapter from model

I'm trying to make changes to my android application by adopting the MVP pattern, but I'm having trouble with where to notify the adapter the recyclerview is using.
What I'm currently doing is giving a reference to the adapter in my model and notifying it as changes are made when click events happen, like so:
public class MyModel {
private MyAdapter adapter;
...
public void setAdapter(MyAdapter adapter) { this.adapter = adapter; }
public void action() {
// make changes to model and notify adapter as changes are
// made to individual items
...
adapter.notifyItemChanged(position)
}
}
I'm wonder what the conventional way of handling this kind of behaviour is using the MVP pattern.
The Observer pattern might be what you are looking for. When changes are made to the model you can notify the Observers (The presenters) so they can then update the view.
http://en.wikipedia.org/wiki/Observer_pattern

How do I refresh a ListFragment from a Asynctask?

I am trying to refresh a ListFragment after Asynctask is finished. In my Asynctask doInBackground method I connect to a database and add elements to an ArrayList. In the onPostExecute method I want to access my ListFragment by something like this to call it's refreshData(method):
//REFRESH ARTISTFRAGMENT
#Override
public void onPostExecute(ArrayList<String> result) {
ArtistFragment artistFrag = new ArtistFragment();
artistFrag = (ArtistFragment) artistFrag.getSherlockActivity().getSupportFragmentManager().findFragmentById(R.id.frame_container);
if (artistFrag != null) {
artistFrag.refreshData(result);
}
}
But getSupportFragmentManager results in a NullPointerException!
The refreshData method in my Fragment looks like this:
public void refreshData(ArrayList<String> data) {
artists = new ArrayList<String>(data);
this.artistAdpater.notifyDataSetChanged();
}
I have found very similar approaches to do the exact thing I want but I can't find a solution to my problem. Basically it's done over here https://stackoverflow.com/a/16388650 - but it doesn't work for me like that.
Has anybody a solution for this or a workaround?
I am assuming that artists is the array list that feeds your listview.
artists = new ArrayList<String>(data);
What you are doing creates a new arraylist object reference to artists. But the list adapter has the older refrence. Thats why the list is not getting update.
Instead of passing the reference of the new arraylist, you can add it to the old one like so:
newArtistsArraylist = new ArrayList<String>(data);
artists .add(newArtistsArraylist );
Here is a nice solution to your problem.

Android is it possible a CustomAdapter update by itself

I will be very grateful if someone can help me one this :)
I have a Custom Adapter (extending ArrayAdapter), and on the objects it displays (movieDatas), there is a property that vary with time (downloadProgress)
Since I use this adapter in multiple places, I wondered wether it is possible for my CustomAdapter to listen to every movieDatas.downloadProgress property, and then update itself ? Thus, not using ArrayAdapter.notifyDataSetChanged from the activity, but the adapter would take the decision to update by itself.
Previously, I used a Timer on every Activity that called myListView.invalidate() every 5 seconds, but I wondered if the adapter could handle the changes by itself ?
Thank you very much for your help, I begin in android development.
I don't know how you're doing it, but it sounds like you could totally use a callback to implement it.
1) Create an interface like this:
public interface OnDownloadProgressChangeListener{
public void onProgress(int progress);
}
2) Add this to your MovieData object:
// We use an ArrayList because you could need to listen to more than one event. If you are totally sure you won't need more than one listener, just change this with one listener
private ArrayList<OnDownloadProgressChangeListener> listeners = new ArrayList<OnDownloadProgressChangeListener>();
public void addDownloadProgressChangeListener(OnDownloadProgressChangeListener listener){
listeners.add(listener);
}
public void clearDownloadProgerssChangeListeners(){
listeners.clear();
}
//Add any handlers you need for your listener array.
// ALWAYS use this method to change progress value.
public void modifyProgress(int howMuch){
progress+=howMuch;
for (OnDownloadProgressChangeListener listener : listeners)
listener.onProgress(progress);
}
3) Override your custom adapter add method
#Override
public void add(final MovieData item){
item.addDownloadProgressChangeListener(new OnDownloadProgressChangeListener(){
public void onProgress(final int progress){
// Add your logic here
if (progress == 100){
item.update();
}
}
});
super.add(item);
}
4) Whenever an item gets modified, call notifyDataSetChanged() on your adapter. You can even add it after the super.add(item) line in the add implementation, but this is extremely inefficient if you're going to add a lot of items: Add them first then notify the changes.

Categories

Resources