应用程序因 ANR::IllegalStateException 崩溃:适配器的内容已更改但 ListView 未收到通知。
application crashed with ANR:: IllegalStateException: The content of the adapter has changed but ListView did not receive a notification.
我用适配器创建了一个列表视图。使用过滤器实现搜索。它工作正常。但有时应用程序会因以下错误而崩溃:
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 activity 中,当用户在文本框中键入内容时,我使用以下代码调用搜索。
@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中我使用过滤器实现了listview中的搜索:
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;
}
使用:mAdapter.notifyDataSetChanged();
在onTextChanged
中调用mAdapter.notifyDataSetChanged()
.
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
.
设置适配器
问题已解决。我移动了代码以将 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;
}
我用适配器创建了一个列表视图。使用过滤器实现搜索。它工作正常。但有时应用程序会因以下错误而崩溃:
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 activity 中,当用户在文本框中键入内容时,我使用以下代码调用搜索。
@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中我使用过滤器实现了listview中的搜索:
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;
}
使用:mAdapter.notifyDataSetChanged();
在onTextChanged
中调用mAdapter.notifyDataSetChanged()
.
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
.
问题已解决。我移动了代码以将 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;
}