我正在使用自定义 ArrayAdapter 在 AutocompleteTextView 上设置适配器(AddressAdapter 扩展 ArrayAdapter)。
public class AutoCompleteAdapter extends ArrayAdapter<String> implements Filterable {
private ArrayList<String> mData;
ArrayList<String> listTempPrefix = new ArrayList<String>();
ArrayList<String> listTemp = new ArrayList<String>();
String valueText;
String[] words;
String ulcase;
public AutoCompleteAdapter(Context context, int textViewResourceId, ArrayList<String> bS) {
super(context, textViewResourceId);
mData = bS;//new ArrayList<String>();
}
@Override
public int getCount()
{
synchronized (listTempPrefix)
{
return listTempPrefix.size();
}
}
@Override
public String getItem(int index)
{
synchronized (listTempPrefix)
{
try {
//Log.e("Error", listTempPrefix.get(index));
return listTempPrefix.get(index);
} catch(IndexOutOfBoundsException e) {
Log.e("Error", "IndexOutOfBoundsException");
return "";
}
}
}
@Override
public Filter getFilter()
{
Filter myFilter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint)
{
FilterResults filterResults = new FilterResults();
synchronized (filterResults)
{
listTempPrefix.clear();
listTemp.clear();
//Log.e("1", "1");
try {
if(constraint != null) {
// A class that queries a web API, parses the data and returns an ArrayList<Style>
//StyleFetcher fetcher = new StyleFetcher();
//try {
//mData = fetcher.retrieveResults(constraint.toString());
//}
//catch(Exception e) {}
// Now assign the values and count to the FilterResults object
for(String value: mData) {
valueText = value.toLowerCase();
//System.out.println("constraintH - " + constraint);
constraint.toString().toLowerCase();
ulcase = constraint.toString().toLowerCase();
//System.out.println("ulcase - " + ulcase);
if (valueText.startsWith(ulcase)) {
listTempPrefix.add(value);
} else {
words = valueText.split(" ");
//final int wordCount = words.length;
// Start at index 0, in case valueText starts with space(s)
for (int k = 0; k < words.length; k++) {
if (words[k].startsWith(ulcase)) {
listTemp.add(value);
break;
}
}
}
///listTemp.add(mData.get(i));
//filterResults.count = mData.size();
// System.out.println("mData" + i + mData.get(i));
}
//Log.e("2", "2");
// System.out.println("size " + listTemp.size() + " value" + listTemp);
listTempPrefix.addAll(listTemp);
filterResults.values = listTempPrefix;
filterResults.count = listTempPrefix.size();
//System.out.println("size " + filterResults.count + " value" + filterResults.values);
//System.out.println("constraint" + constraint);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return filterResults;
}
}
@Override
protected void publishResults(CharSequence contraint, FilterResults filterResults)
{
synchronized (filterResults)
{
if(filterResults != null && filterResults.count > 0) {
notifyDataSetChanged();
//Log.e("notifyDataSetChanged", "notifyDataSetChanged");
}
else {
notifyDataSetInvalidated();
//Log.e("notifyDataSetInvalidated", "notifyDataSetInvalidated");
}
}
}
};
return myFilter;
}
我有时遇到的情况:请注意,这种情况很少发生。但我想完全摆脱这个错误。这是部分堆栈跟踪:
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.example.test.AutoCompleteAdapter)].
问题可能是来自键盘的快速输入,方法 notifyDataSetChanged () 未被调用。但我不确定。
最佳答案
将 publishResults 更改为
@Override
protected void publishResults(final CharSequence contraint, final FilterResults filterResults) {
listTempPrefix = (List) results.values;
if(filterResults != null && filterResults.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
这样 GUI 线程更新结果而不是在后台线程中运行的 performFiltering。
从 performFiltering 中删除 listTempPrefix 引用并在那里使用局部变量来存储结果并通过 FilterResults 返回它们
关于android - 非法状态异常 : The content of the adapter has changed but ListView did not receive a notification,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13156299/