I have a list of key words (about 1000 words) and i set this to an ArrayAdapter to be handled by AutoCompleteTextView. The basic process works fine. The problem arise when i selected a long word (10 character above), then use the keyboard backspace button to remove the word (press and hold on the button), after removing like 5 characters the app crashes with the following error.
01-16 13:27:23.082: ERROR/AndroidRuntime(2874): FATAL EXCEPTION: main
java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(-1, class android.widget.AutoCompleteTextView$DropDownListView) with Adapter(class com.hdm_i.dm.corp.android.muenchen.adapters.PoiAutoCompleteAdapter)]
at android.widget.ListView.layoutChildren(ListView.java:1527)
at android.widget.AbsListView.onLayout(AbsListView.java:1430)
at android.view.View.layout(View.java:7228)
at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
at android.view.View.layout(View.java:7228)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1145)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1865)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:842)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:600)
at dalvik.system.NativeStart.main(Native Method)
Below is my code, did i do anything wrong ? Thanks in advance for your suggestions :-)
public class PoiAutoCompleteAdapter extends ArrayAdapter<SearchTextAutoSuggest> implements Filterable {
private List<SearchTextAutoSuggest> searchTextAutoSuggestList = new ArrayList<SearchTextAutoSuggest>();
private SearchTextAutoSuggest defaultSuggestion = new SearchTextAutoSuggest();
private Handler uiThreadHandler;
public PoiAutoCompleteAdapter(Context context, int viewResourceId, Handler uiThreadHandler) {
super(context, viewResourceId);
this.uiThreadHandler = uiThreadHandler;
defaultSuggestion.setName(AppConstants.DEFAULT_SEARCH_STRING_NAME);
}
@Override
public int getCount() {
return searchTextAutoSuggestList.size();
}
@Override
public SearchTextAutoSuggest getItem(int position) {
return searchTextAutoSuggestList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public Filter getFilter() {
Filter filter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
synchronized (filterResults) {
if (constraint != null) {
// Clear and Retrieve the autocomplete results.
searchTextAutoSuggestList.clear();
searchTextAutoSuggestList = getFilteredResults(constraint);
// Assign the data to the FilterResults
filterResults.values = searchTextAutoSuggestList;
filterResults.count = searchTextAutoSuggestList.size();
}
return filterResults;
}
}
@Override
protected void publishResults(CharSequence constraint, final FilterResults filterResults) {
uiThreadHandler.post(new Runnable() {
public void run() {
synchronized (filterResults) {
if (filterResults != null && filterResults.count > 0) {
notifyDataSetChanged();
} else {
Logs.e("Tried to invalidate");
notifyDataSetInvalidated();
}
}
}
});
}
};
return filter;
}
private List<SearchTextAutoSuggest> getFilteredResults(CharSequence constraint) {
List<SearchTextAutoSuggest> searchTextAutoSuggestList = AppContext.searchTextAutoSuggestList;
List<SearchTextAutoSuggest> filteredSearchTextAutoSuggestList = new ArrayList<SearchTextAutoSuggest>();
// Assign constraint as a default option into the list
defaultSuggestion.setLabel(getContext().getString(R.string.general_default_search_str) + " \'" + constraint + "\'");
filteredSearchTextAutoSuggestList.add(defaultSuggestion);
for (int i = 0; i < searchTextAutoSuggestList.size(); i++) {
if (searchTextAutoSuggestList.get(i).getLabel().toLowerCase().startsWith(constraint.toString().toLowerCase())) {
filteredSearchTextAutoSuggestList.add(searchTextAutoSuggestList.get(i));
}
}
return filteredSearchTextAutoSuggestList;
}
}
because performFiltering
executes in worker thread. And you assign your searchTextAutoSuggestList variable in this thread, but you have to change data of the adapter only in UI thread. Also publishResults
method executes in UI thread so you don't need any Handlers here.
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
synchronized (filterResults) {
if (constraint != null) {
// Clear and Retrieve the autocomplete results.
List<SearchTextAutoSuggest> resultList = getFilteredResults(constraint);
// Assign the data to the FilterResults
filterResults.values = resultList;
filterResults.count = resultList.size();
}
return filterResults;
}
}
@Override
protected void publishResults(CharSequence constraint, final FilterResults filterResults) {
if (filterResults != null && filterResults.count > 0) {
searchTextAutoSuggestList.clear();
searchTextAutoSuggestList = filterResults.values;
notifyDataSetChanged();
} else {
Logs.e("Tried to invalidate");
notifyDataSetInvalidated();
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With