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)
Related
I'm trying to populate a listView, but if I initialize it after onCreate it doesn't appear. I tried to initialize it into the onCreate and use adapter.notifyDataSetChanged(); after I insert values into my String array used to populate the listView but I have no success.
Does someone know how to solve this problem? I checked other questions but I didn't find an answer to my problem.
Thanks in advance.
Maybe you need to call adapter.notifyDataSetChanged() inside the UI thread.
Also it's better to use an ArrayList<String> instead of a String[]
Keep references to both the ArrayList and ArrayAdapter inside your activity class.
private ArrayList<String> items;
private ArrayAdapter<String> adapter;
Initialize your ArrayList<String> and set adapter in your onCreate
items = new ArrayList<String>();
// add initial items
items.add("1st item");
// create adapter
adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items);
// set the adapter
listView.setAdapter(adapter);
Now whenever you want to change the items, call the add(), remove(), etc methods of the ArrayList and subsequently call adapter.notifyDataSetChanged(). The change to the ArrayList can be done in any thread, but adapter.notifyDataSetChanged() should be called in UI thread.
For example in a button press you might wanna do
items.add("New item");
adapter.notifyDataSetChanged();
Also you might wanna check these:
this and
this
PS: Sorry for my bad posting skills. I'm new.
My data are defined in a global variable ArrayList cells and my custom ArrayAdapter holds a reference to that variable:
class CellAdapter extends ArrayAdapter<Cell> {
CellAdapter() {
super(context, 0, 0, cells);
}
}
Then I have a method in which i refresh the cells by calling clear() and then using the add() method. After doing this, then I call:
adapter.notifyDataSetChanged();
The adapter should still hold a reference to the global variable with which I have initialized it, right? Anyway, it's not working. What am I doing wrong?
adapter.clear() is calling cells.clear() since the super class holds a reference to your ArrayList<Cell>. He works, but you are filling up the adapter with an empty dataset.
An ArrayAdapter does not make a copy of your cells array list. Whenever you make modifications to the objects inside the cells array, you can just call notifyDataSetChanged on it.
If you modify the list itself (especially removing items from the list) you must notify the adapter, otherwise it will start throwing exceptions.
adapter.clear();
is clearing your cells object as well.
Just don't call clear and addAll
If you have updated your cells list then just call:
adapter.notifyDataSetChanged();
It will refresh
I used notifyDataSetChanged for adapter but my List didn't updated. Here is part of my code.
adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,userNames);
list = (ListView) findViewById(R.id.listViewUsers);
list.setAdapter(adapter);
SO every time I'm adding item to userNames , I'm calling adapter.notifyDataSetChanged(); method, but there are no any updates. I tried many things with cleaning , clearing userNames but it's not working.
Can anyone help me?
Thanks
EDIT:
I'm calling these two functions where I'm adding new user.
userNames.add(user.getUsername());
adapter.notifyDataSetChanged();
Also I have User class, but I fill in ListView with users' usernames.
Try add username directly to adapter instead of adding to userNames. Maybe when you create a new instance of ArrayAdapter, it will create a new private List inside adapter and you add username to old instance of userNames :
adapter.add(user.getUsername());
adapter.notifyDataSetChanged();
For an ArrayAdapter, notifyDataSetChanged() only works if you use the add, insert, remove, and clear functions on the Adapter.
When an ArrayAdapter is constructed, it holds the reference for the List that was passed in. If you were to pass in a List that was a member of an Activity, and change that Activity member later, the ArrayAdapter is still holding a reference to the original List. The Adapter does not know that you changed the List in the Activity.
Try this:
userNames.add(user.getUsername());
adapter.clear();
adapter.addAll(userNames);
adapter.notifyDataSetChanged();
Consider the following code.
List<String> list = new ArrayList<String>();
ArrayAdapter<String> adapter = new ArrayAdapter<String>(context, resource, textViewResourceId, list);
// Method 1 : Add an item.
adapter.add("ITEM1");
// Method 2 : Add an item
list.add("ITEM2");
I was wondering, which is the correct way to add item into ArrayAdapter? As seems to me, both methods just work fine.
Method 1 updates the associated AdapterView, if you have already attached the ArrayAdapter to the AdapterView. Method 2 does not, requiring you to call notifyDataSetChanged() on the ArrayAdapter.
Typically, you populate the ArrayList before creating the ArrayAdapter, then use Method 1 to add new entries dynamically later on (e.g., based on user data entry).
This is what I do, especially for my Search Results page - where it grows as the user scroll down (list changes).
I'd keep a local ArrayList of Strings that is global to the class,
Initialize the adapter (also locally and globally),
Have a designated method alter the ArrayList of strings,
Then call the adapter.notifyDataSetChanged();
This will not only update your list and also update the adapter to work in sync.
Hope this helps,
best,
-serkan
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);
}
}