Notify dataset changed not fetching new data for the recyclerview - android

I have a recyclerview that is not updating and I am not sure why:
In my main fragment I get the data for the my recyclerview in oncreateview like this:
alarms = AlarmCollection.getAlarms(getActivity());
and then I set the adapter like this:
// Adapter
adapter = new AlarmsAdapter(getActivity(), alarms);
rv.setAdapter(adapter);
And then I reset the data on a timertask/runnable to update the values of on the recyclerview (they are alarms so they change once a minute).
This is done through a simple notify datasetchanged:
adapter.notifyDataSetChanged();
The problem is though as you can see above I load the data through AlarmCollection. This is grabbing the list from the shared preferences.
But when I am calling notify dataset changed this is not being called again.
I was under the impression that when you call notify ect on a recyclerview it would update the list or does it pureley update the view?

As #GpRyan mentioned, the problem lies in this line :
alarms = AlarmCollection.getAlarms(getActivity());
Every time you make a new instance of alarms.But the adapter is looking for changes in the instance of alarms you passed to it. so it won't work.
what you should do is removing all items from alarms and add your new data again.
alarms.removeAll();
alarms.addAll(AlarmCollection.getAlarms(getActivity()));
adapter.notifyDataSetChanged();
NOTE: Update the alarmsin your main thread. Once, it takes me a long time that i understand updating the data set in another thread
wont work with adapter.

notifyDataSetChanged() only updates the view. Typically what you'll do is call notifyDataSetChanged() after you've modified the data that the adapter holds (in your case alarms.
So what you should be doing is: updating alarms inside of your timer task / runnable, and then calling notifyDataSetChanged()

If your getItemCount() returns 0, then notifyDataSetChanged() won't do anything.
make sure you have added getItemCount() in your RecyclerView Adapter.
#Override
public int getItemCount() {
return alarms.size();
}
EDIT : you can also use notifyitemrangechanged
adapter.notifyItemRangeChanged(0,alarms.size());

Related

Is there an event called by changing the count of items in the recyclerview?

Is there an event called by changing the count of items in the recyclerview?
I want to call function every time recyclerview items are added.
Update:
It turns out I misunderstood the original question. What was really asked is how to get notified when the underlying data in an Adapter has changed.
For this you could use a RecyclerView.AdapterDataObserver in conjunction with RecyclerView.Adapter's registerAdapterDataObserver(AdapterDataObserver observer) method to register for changes in the underlying list data.
Original Answer:
Your RecyclerView is backed by a RecyclerView.Adapter which owns the actual list of items being displayed.
If you change the backing list, you should call one of the notifyXXX methods on your adapter to notify your RecyclerView what has changed (and optionally where in the list the change happened.)
At the very least, you could call notifyDataSetChanged on your adapter to tell your RecyclerView that something somewhere in the list has changed. This can be expensive since you're not being specific about what changed, so the RecyclerView has to query the adapter for more information and potentially redraw its entire client area of items.
Something like:
RecyclerView.Adapter adapter = recyclerView.getAdapter();
if (adapter != null) {
adapter.notifyDataSetChanged();
}
Behind the scenes, the RecyclerView will call the RecyclerView.Adapter#getItemCount() method on the Adapter to determine what the current item count is.

ListView refresh taking it to the top of the list

Scenario: I am using a listview with custom Adapter. I am fetching data every 5 seconds and then displaying it in the listview.
Problem: After every refresh the list scrolls at the top. I would want the list to stay as is from the scroll standpoint and just the underlying data to be refreshed.
Current code: This is called every time I fetch a new data.
mListAdapter = new CustomListAdapter(this, mListData);
mList.setAdapter(mListAdapter);
Instead of your code please try to put every time you fetch data this one:
adapter.notifyDataSetChanged();
Instead of calling this, you should set the new data to the adapter and then call notifyDataSetChanged.
Hope this helps!
As you get new mListData then just invalidate the adapter not re-initialized the adapter you can call like this
mListAdapter.notifyDataSetChanged();
You can use
mList.setSelection(mListData.size() - CONSTANT.CONTENT_SIZE);
This way the listview will not refresh to the top.
Or you can also use
adapter.notifydatasetchanged
by updating the binded list.
This Worked For Me:
adapter.setData(list);
adapter.notifyDataSetChanged();

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);
}
}

notifyDataSetChanged() does not update the listview

I have a list of 4 items, I have used listview. I want to change a string dynamically on recieving internal event. I see that when I receive the event I am setting the string correctly but and then calling
mAdapter.notifyDataSetInvalidated();
mAdapter.notifyDataSetChanged();
but the list is not getting updated.
I've had the same experience. The cause was that the list adapter was updating on the wrong thread i.e. not the UI thread. This is easily solved by changing the adapter data on the UI thread through (as I found on other posts):
runOnUiThread(new Runnable() {
public void run() {
// code that changes the list adapter data
}
});
Of course you can always create a (inner) class that implements Runnable that is provided with the list adapter and data to add, insert etc.
Note: calling notifyDataSetInvalidated() or notifyDataSetChanged() will not be necessary as it is called by default, unless you turned it off explicitly with setNotifyOnChange(false);
I think that notifyDataSetChanged only works if you use the add (or insert), remove or clear functions on adapter.
You can rebuilt the list adapter for force to refresh the listView.
Excuse me for my bad english

How to update a spinner dynamically?

I've been trying to update my spinner in android dynamically but nothing I try has been working.
This is the following code I'm using to update the spinner.
typeList = dbAdapter.getList(); //array list with the values
adapter.notifyDataSetChanged();
groupSpinner.postInvalidate();
groupSpinner.setAdapter(adapter);
The values of typeList are correct but they're not being updated in the Spinner.
Actually, you either have to call clear/add on the adapter, or create and set a new adapter. The adapter does not retain a reference to your list (it is only calling toArray on your list at construction), so there is no way for it to update itself.
dataAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, newStringList);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinnerCategory.setAdapter(dataAdapter);
You can't directly modify the original List then call notifyDataSetChanged() like on other adapters, as it doesn't hold on to the original List.
You can, however, achieve the same result using the adapter itself, like so:
spinnerAdapter.clear();
spinnerAdapter.addAll(updatedListData);
spinnerAdapter.notifyDataSetChanged(); // optional, as the dataset change should trigger this by default
Based on this answer from user392117.
edit: By default, methods that change the list like add() and remove() automatically call notifyDataSetChanged() (see Android Developer Documentation for setNotifyOnChange(boolean) )
public void setNotifyOnChange (boolean notifyOnChange)
Control whether methods that change the list (add, addAll(java.util.Collection), addAll(java.lang.Object[]), insert, remove, clear, sort(java.util.Comparator)) automatically call notifyDataSetChanged. If set to false, caller must manually call notifyDataSetChanged() to have the changes reflected in the attached view. The default is true, and calling notifyDataSetChanged() resets the flag to true.
So you should not need to call notifyDataSetChanged() every time. If you find that this is the case, you can use setNotifyOnChange(true)
spinnerAdapter.setNotifyOnChange(true); //only need to call this once
spinnerAdapter.add(Object); //no need to call notifyDataSetChanged()
You only need to call setAdapter() once and you call adapter.notifyDataSetChanged() to update the data.
When you have data changed in your list and when you want to update
the spinner then
Create a new object of the adapter and set that adapter to the
spinner. It will work sure.
Best of luck.
Edit: Also you need to call notifyDataSetChanged() on the adapter.
Is there a typo or something? Which is the difference between dbAdapter and adapter. If the Spinner has already the adapter, you don't have to re-assign it. More over, the only think you have to do is update the adapter and call notifyDataSetChanged method.
typeList = adapter.getList(); //array list with the values
// change the values, and then
adapter.notifyDataSetChanged();
Using add/remove on your adapter and using notifyDataSetChanged() enables you not having to create new adapters over and over again.
Declare your adapter global
ArrayAdapter<Object> adapter;
When you add something to the List of Objects the adapter is attached to (Strings or whatever object you use) add an add function to the adapter and call notifyDataSetChanged:
adaper.add(Object);
adapter.notifyDataSetChanged();
and when you remove an item from the List add also:
adapter.remove(Object);
adapter.notifyDataSetChanged();
edit: By default, methods that change the list like add() and remove() automatically call notifyDataSetChanged() (see Android Developer Documentation for setNotifyOnChange(boolean) )
public void setNotifyOnChange (boolean notifyOnChange)
Control whether methods that change the list (add, addAll(java.util.Collection), addAll(java.lang.Object[]), insert, remove, clear, sort(java.util.Comparator)) automatically call notifyDataSetChanged. If set to false, caller must manually call notifyDataSetChanged() to have the changes reflected in the attached view. The default is true, and calling notifyDataSetChanged() resets the flag to true.
So you should not need to call notifyDataSetChanged() every time. If you find that this is the case you you can use setNotifyOnChange(true)
adapter.setNotifyOnChange(true); //only need to call this once
adapter.add(Object); //no need to call notifyDataSetChanged()
Change the underlying data and call the notifyDataSetChanged() on adapter.
list.clear();
list.add("A");
list.add("B");
dataAdapter.notifyDataSetChanged();
After you change your data, you will need to add the following code:
typeList = dbAdapter.getList()
adapter = new ArrayAdapter<String>(v.getContext(),
android.R.layout.simple_spinner_dropdown_item,typeList);
groupSpinner.setAdapter(adapter);
Apparently after you do typeList = dbAdapter.getList(), the variable typeList points to a different List rather than the one you fed to the adapter originally and the adapter would be somewhat confused.
So you should use the following code:
typeList.clear();
typeList.addAll(dbAdapter.getList());
When you set up the spinner adapter add
spinnerAdapter.setNotifyOnChange(true);
From then on when you add new data it will be automatically updated.
First of all, you have to initialize the adapter with ArrayList<T>. Otherwise, you might get an exception.
val list: ArrayList<String> = arrayListOf()
private lateinit var spinnerAdapter: ArrayAdapter<String>
After that initialize the adapter:
spinnerAdapter = ArrayAdapter<String>(requireContext(),
android.R.layout.simple_spinner_item,
list) // initialize with empty arrayList
spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
binding.spinnerCurrency.apply {
adapter = spinnerAdapter
}
After that when you have data clear and add all list.
spinnerAdapter.clear()
spinnerAdapter.addAll(list)

Categories

Resources