I am having a weird issue with a custom Android implementation of ArrayAdapter. To give some background, I am trying to update the contents of a ListView while maintaining the current scroll position.
I have a service that runs a thread to update the data displayed in a ListView. This data is stored in an ArrayList and that an ArrayList is used to create some custom ArrayAdapters for the ListView. Adapters are also updated when an item in a ListView is clicked (add or remove an item). Previously, I simply created new adapters every time I made any changes, and then installed this new adapter in the ListView. This worked, but each time the ListView scrolled up. Given the nature of my application, this was undesirable. The current scroll position in the ListView must be maintained between updates.
Instead of creating new adapters, I started to clean the adapter, which I need to update using the adapter's clear () method, and then rebuild the adapter elements using the adapter's add () method. Both of these methods are called on the adapter. All adapters are configured for notifyDataOnChange in their constructors, so I do not need to manually call notiftyDatasetChanged () every time (although, given my problem, I tried to call it manually, and also to no avail).
Here's what my custom adapter looks like:
public class RealmAdapter extends ArrayAdapter<Realm> { Context c; public RealmAdapter(Context context, int resource, int textViewResourceId) { super(context, resource, textViewResourceId); setNotifyOnChange(true); c = context; } @Override public View getView(int position, View convertView, ViewGroup parent) { ... } ... }
In short, here is my problem. When I call clear () on the adapter, the adapter does not clear.
Here is a snippet of my onPostExecute in my thread that is performing the update. I am sure I put it here so that it is updated in the user interface thread. I also have this exact code copied in a private method in my user interface. This code does not work in any place:
appState.favoriteAdapter.clear(); Log.d(LOG_TAG, "COUNT: " + appState.favoriteAdapter.getCount()); for(Realm r : appState.favorites) { appState.favoriteAdapter.add(r); } Log.d(LOG_TAG, "COUNT: " + appState.favoriteAdapter.getCount());
As an example, if the above adapter had 3 elements in it, calling getCount () immediately after clear () returns 3 instead of 0. Similarly, if appState.favorites ArrayList has only 2 elements, getCount () after the loop still returns 3, not 2. Since the adapter does not answer any of these calls, it makes updating impossible in any way. I can publish Logcat later if it is useful, but there are no exceptions or anything useful displayed.
After long tears in my head, the problem I see is that the adapter does not answer calls to any methods that change it. I tried passing an empty ArrayList to the adapter's super () call, this will not help. Am I missing something or using the ArrayAdapter incorrectly? I searched everything and I already checked many common problems, such as changing the base array and waiting for it to update, rather than calling (or in the settings of my adapter cover) notifyDatasetChanged () and using an unsupported operation on the base collection.
Declaring a favorite adapter is very simple and is contained in my Application class:
public RealmAdapter favoriteAdapter;
Here's the initialization of your favorite adapter on top:
if(appState.favoriteAdapter == null) { appState.favoriteAdapter = new RealmAdapter(c, R.layout.list_item, R.layout.realm_entry, appState.favorites); } else { appState.favoriteAdapter.clear(); Log.d(LOG_TAG, "COUNT: " + appState.favoriteAdapter.getCount()); for(Realm r : appState.favorites) { appState.favoriteAdapter.add(r); } Log.d(LOG_TAG, "COUNT: " + appState.favoriteAdapter.getCount()); }
The above code is in both my user interface thread and the thread that downloads the updated data.
Under the code above the filter is installed:
if(appState.favoriteAdapter != null && RealmSelector.realmFilter != null) appState.favoriteAdapter.getFilter().filter(RealmSelector.realmFilter.getText().toString());
Will the filter affect the cleaning of the list? Logic will not dictate ...