我用适配器创建了一个listview。使用过滤器实现搜索。它工作正常。但有时应用程序崩溃时出现以下错误:
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. Make sure your adapter calls notifyDataSetChanged() when its content changes.
在ListView活动中,当用户在文本框中输入内容时,我使用以下代码调用搜索。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.list_view_layout);
mAdapter = new ListViewAdapter(this);
...
mSearchEditText = (EditText) findViewById(R.id.search_text);
mSearchEditText.addTextChangedListener(new TextWatcher() {
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
Log.v("ListViewActivity", "SearchTextBox: onTextChanged <" + s + ">");
mAdapter.getFilter().filter(s);
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void afterTextChanged(Editable s) {
}
});
在ListViewAdapter中,我使用过滤器在列表视图中实现搜索:
public class ListViewAdapter extends BaseAdapter implements Filterable{
private ArrayList<ListItem> mOriginalList;
private ArrayList<ListItem> mDisplayedList;
...
@Override
public Filter getFilter() {
Filter filter = new Filter() {
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
Log.v("ListViewAdapter", "Filter: publishResults constraint<" + constraint + ">");
notifyDataSetChanged();
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
Log.v("ListViewAdapter", "Filter: performFiltering constraint<" + constraint + ">");
FilterResults filterResults = new FilterResults();
mDisplayedList.clear();
if (constraint == null || constraint.length() == 0) {
mDisplayedList.addAll(mOriginalList);
filterResults.count = mDisplayedList.size();
filterResults.values = mDisplayedList;
} else {
String searchText = constraint.toString().toLowerCase();
for (ListItem listItem : mOriginalList) {
if (listItem.getKeyName().toLowerCase().contains(searchText)
|| listItem.getKeyValue().toLowerCase().contains(searchText)) {
mDisplayedList.add(listItem);
}
}
filterResults.count = mDisplayedList.size();
filterResults.values = mDisplayedList;
}
Log.v("ListViewAdapter", "Filter: performFiltering filterResults.count<" + filterResults.count + ">");
return filterResults;
}
};
return filter;
}
答案 0 :(得分:0)
使用:mAdapter.notifyDataSetChanged();
答案 1 :(得分:0)
在onTextChanged
中,拨打mAdapter.notifyDataSetChanged()
。
答案 2 :(得分:0)
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. Make sure your adapter calls notifyDataSetChanged() when its content changes.
出现此问题是因为您在主线程上设置了适配器。而不需要在UI thread
中设置适配器。与使用AsyncTask
方法中的onPostExecute()
设置适配器或使用onHandledMessage()
Handler
方法Thread
方法一样。
答案 3 :(得分:0)
问题已解决。我移动代码将mDisplayedList更新为publishResults(),而不是在performFiltering()for循环中继续更新。更新mDisplayedList并一起调用notifyDataSetChanged()。我认为这是最好的解决方案。
@Override
public Filter getFilter() {
Filter filter = new Filter() {
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
Log.v("ListViewAdapter", "Filter: publishResults constraint<" + constraint + ">");
if (results.count == 0) {
mDisplayedList.clear();
notifyDataSetInvalidated();
} else {
mDisplayedList.clear();
mDisplayedList.addAll((ArrayList<ListItem>) results.values);
notifyDataSetChanged();
}
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
Log.v("ListViewAdapter", "Filter: performFiltering constraint<" + constraint + ">");
FilterResults filterResults = new FilterResults();
ArrayList<ListItem> filteredList = new ArrayList<ListItem>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(mOriginalList);
} else {
String searchText = constraint.toString().toLowerCase();
for (ListItem listItem : mOriginalList) {
if (listItem.getKeyName().toLowerCase().contains(searchText)
|| listItem.getKeyValue().toLowerCase().contains(searchText)) {
filteredList.add(listItem);
}
}
}
filterResults.count = filteredList.size();
filterResults.values = filteredList;
Log.v("ListViewAdapter", "Filter: performFiltering filterResults.count<" + filterResults.count + ">");
return filterResults;
}
};
return filter;
}