adapters notifyDataSetChanged does not work - android

EDIT 2:
I did solve my problem, but i don't know how:S I was moving my code snippets a bit around, a suddenly it worked. Must have done something in the wrong order, but its weird, checked it many times. Thanks for you help, and sorry I can't post an answer ;)
Hi.
I have a list view which I'm trying to refresh to update it self when i add an element to
the underlying array list.
Here is the code snippet:
private void addEvent() {
arrlEvents.add( event );
adptEvents.notifyDataSetChanged();
updateSaveFile();
filterList();
}
The arrlEvents is the underlying arraylist with the events, and im adding one event, trying to update the list view with notifyDataSetChanged(), but it doesnt work. Can anyone help?
Thanks for your time:)
EDIT:
Here is the source code for the adapter:
private ArrayAdapter<Event> adptEvents;
adptEvents = new ArrayAdapter<Event>( EventCalendar.this, R.layout.list_items, arrlEvents );

I have seen that sometimes it just randomly doesnt notify the adapter.
Try using adptEvents as protected or public on a global scope.
I have found that when that doesnt work. You can just re set the adapter again, just substitute the notifyDataSetChanged() for:
adptEvents = new ArrayAdapter<Event>( EventCalendar.this, R.layout.list_items, arrlEvents );
Edit:
Heres a code snipper from an App I wrote that works.
Class definition:
public class ClassName extends ListActivity implements AdapterView.OnItemSelectedListener {
Global Variable:
CustomAdapter adapter;
in OnCreate():
adapter = new CustomAdapter(this,R.layout.layout_name,dataSet);
setListAdapter(adapter);
Whenever I need to notify
adapter.notifyDataSetChanged();

There is no persistent link between arrlEvents and the adptEvents.... the latter simply initialises itself with the elements from the former. adptEvents has no way to know when arrlEvents changes.
To add new items you should call adptEvents.add(event) and not bother calling notifyDataSetChanged() explicitly, since ArrayAdapter.add() does that for you automatically.

Related

Not sure how to deal with ListView IllegalStateException: “The content of the adapter has changed but ListView did not receive a notification”

Sorry for a brick of a code but I read that I need to run something on UI thread, how do I do that? private ArrayList JsonFIveDays(String weatherSearchResults) is where I set my listview adapter if that helps.
You have to notify the adapter whenever you do changes in the weatherArrayList.
For Example,
weatherAdapter.notifyDataSetChanged()
But in your case to use like that you have to declare the weatherAdapter as a property of the class.
I hope it will help you.
You need to notify adapter that you changed data with notifyDataSetChanged(). You can do that in setData method after changing data.

Using an ArrayAdapter with LiveData.

I'm familiar with MVVM in WPF, but am in the process of porting an existing Android app to make use of a ViewModel class and LiveData for the first time.
The app "as/was" has a custom ArrayAdapter that is used to correctly display the items contained in a List in a gridview. The code that does that looks essentially like this ("essentially" because there are actually 4 such grids in the activity that all do it like this):
ArrayAdapter<String> playerAdapter = new MyAdapter<String>(this, R.layout.grid_item, playerList);
gridView.setAdapter(playerAdapter)
and when the playerList contents changed, there was an explicit call to
playerAdapter.notifyDataSetChanged()
Since my goal is to have the grid respond automatically when the playerList changes, and never have to notify anything, it seems now that the "playerList" needs to become a MutableLiveData<List<String>>.
I suspect I am going to have a problem though-
The MyAdapter class extends ArrayAdapter<T>
So in practice it's going to become an
ArrayAdapter<MutableLiveData<List<String>>>
But a MutableLiveData isn't going to work there, right?
I could unwrap it and make the call to create it look like this:
ArrayAdapter<String> playerAdapter =
new MyAdapter<String>(this, R.layout.grid_item, playerList.getValue());
Is this correct? It seems the way of madness.
Ultimately my goal is to just assign the gridView's android:adapter property to this thing in xml and never have to think about it anymore (beyond the required calls to setvalue() and postValue() when I modify the underlying list...which I'm not even sure how would work here.
I would hope there's already a MutableLiveData Collection that's ready to go somewhere and I'd use that.
What the standard way to do this?
I believe the way you are thinking is wrong. Don't worry about this:
ArrayAdapter<MutableLiveData<List<String>>>
You will get a list thats all. MutableLiveData is to set a livedata object like setValue() or postValue() manually. Just set your below code whenever liveData gets triggered and gives you the new playerList, something like this:
viewModel.getPlayListObservable().observe(this, new Observer<List<String>>() {
#Override
public void onChanged(List<String> playerList) {
ArrayAdapter<String> playerAdapter = new MyAdapter<String>(this, R.layout.grid_item, playerList);
gridView.setAdapter(playerAdapter);
playerAdapter.notifydataChanged();
}
});

Android RecyclerView.Adapter notifyItem drives me crazy

I searched for hours but still have no explanation (even not in official docu) what is the right way to use a RecyclerView.Adapters' notify-methods. Already read a lot of similar question on SO, but no could solve my simple problem. I try to put down a short, simplified example.
class MyAdapterClass extends RecyclerView.Adapter<MyAdapterClass.MyViewHolderClass> {
...
List myItemList = new ArrayList<MyItemType>();
...
}
RecyclerView myRecView = (RecyclerView) findViewById(R.id.myRecView);
myRecView.setAdapter(new MyAdapterClass(...)));
Even when inserting the first item, the view is not refreshed.
myAdapter.myItemList.add(newItem);
myAdapter.notifyItemInserted(myAdapter.myItemList.size() - 1);
If I then tightly touch (try to scroll) the 1-item-listview, the item appears. So it seams to be a refreshing issue. But why? I have an emtpy list, then I insert one item, then I notify the adapter about the insertion. Whats wrong with my expectation?
By the way, even if I additionally call:
myAdapter.notifyItemChanged(myAdapter.myItemList.size() - 1);
it gets not automatically refreshed.
EDIT: And of course, I dont want to use notifyDataSetChanged() :-) only insert, update, remove on an existing list.
Try to add this code inside your adapter class :
#Override
public int getItemCount() {
return myItemList.size();
}
i hope you define in adpter getItemCount() in list size. then used blow code for notify adapter.
myadapter.notifyItemRangeChanged(0, userDataArrayList.size());

Live Update ListView

I have dug deep down into SO but, although I have found other people asking similar questions to mine, I have not yet find a question that addresses the same issues I have. I have not found a satisfying answer either.
I have a ListView. When I call from the adapter, .notifyDataSetChanged, the ListView is updated, but I can see the update only once onResume() is called. In other words, I do not see it instantly, only after I leave the activity and comeback.
What can I do to see the update instantly? I have tried the .notifyDataSetChanged method, I have tried resetting the adapter... nothing worked.
According to your comment, you dont update the array IN the adapter, but an array held by the activity you passed to the adapter once. Thats why the adapter isnt updating properly. You are changing the array outside of your adapter-class, which might not be the same array-object your adapter is using. At onResume(), your adapter is recreated with the new array and showing the new content.
A solution would be using the following custom Adapter class:
class MyAdapter extends BaseAdapter {
private Array[] myArray;
public MyAdapter(Array[] myArray) {
this.myArray = myArray;
}
public updateContent(Array[] myNewArray) {
this.myArray = myNewArray;
this.notifyDataSetChanged();
}
// your getItem, getView, and so on methods
}
Then from your activity, simple call myArray.updateContent() with your new Array and it will update immediatly.
Its never good to hold and manipulate an object used from one class (the adapter) within another one (the activity). Try to move all code for manipulating the array into the adapter and use methods to add/remove items. This will make it a lot easier finding this kind of errors!

Android: Possible solution for updating the custom list view at random times

I am having a situation where I want to update my Custom List View using BaseAdapter whenever my Database is updated. I have tried calling invalidate() on this Custom List but it didn't work, similarly I even tried having a timer to update my list after sometime, that didn't work either. Please let me know of possible solution.
Update:
This is how I am making my custom list view
li= (ListView)findViewById(R.id.id_lv_row);
ColorDrawable divcolor = new ColorDrawable(Color.DKGRAY);
registerForContextMenu(li);
li.setDivider(divcolor);
li.setDividerHeight(2);
li.setAdapter(new FriendsPositionAdapter(this));
BaseAdapter.notifyDataSetChanged() should do the trick as long as the data behind the adapter actually changed. That's all you need to do to refresh the list.
Invalidate is for repainting views only, you have to tell to the List adapter (BaseAdapter) that dataset has changed.
When the data changes, asign the new dataset to the adapter, and later call notifyDataSetChanged()...
in order to make functional notifyDataSetChanged() the adapter data must be changed. Remember that the original data that change is not reflected automatically to the adapter.
//here i retrieve the new list, named "beans"
lista = (BeanList) result.getDataObject();
Vector<Bean>beans = list.getBeanList();
((BeanListAdapter)listAdapter).syncData(beans);
((BeanListAdapter)listAdapter).notifyDataSetChanged();
//now the syncData method
public void syncData( List<PINPropiedad> newData ){
for(Object o : newData){
add(o);
}
}

Categories

Resources