When setting adapter for listView, should I just do listView.setAdapter(new MyAdapater()); or should I keep the adapter as instance variable and set it to null when onDestory() ?
The answer depends on the use case.
If you are going to do data manipulation such as rearranging the order of elements or changing the data dynamically in some way, then its "better" to have an instance variable of your adapter. It will safe you from casting your adapter from ListView getAdapter() method, whenever accessing your adapter.
If you are creating a simple list view consisted of for ex. 10 Strings and you dont plan on doing anything with the data set, then you don't need to keep a reference to your adapter.
It is better to maintain adapter as instance variable because each and every time you have to create new adapter instead of that just change the data and you can call notifyDatasetChanged() so that adapter will be refreshed.
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();
I know I can update the array which was initally passed to the arrayAdapter's constructor, and call notifyDataSetChanged.
I wonder if it's possible to plug-in new arraylist into adapter?
simple:
mAdapter.clear();
mAdapter.addAll(collection);
also, do add individual elements you can call mAdapter.add(element); instead of having to keep a reference to the Array that was passed to the constructor.
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);
}
}
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)