Java 在android阵列适配器中使用notifyDataSetChanged时出错
11-06 19:52:25.958:E/AndroidRuntime(29609): java.lang.IllegalStateException:适配器的内容已更改 已更改,但ListView未收到通知。确保 适配器的内容不是从后台线程修改的,而是 仅从UI线程。[在ListView中(-1,类 带有适配器(类)的android.widget.ListPopupWindow$DropDownListView) com.example.parkfoxxlight\u android.PlacesAutoCompleteAdapter)] 完整日志: 适配器的完整代码:我使用的是来自的示例,它有相当多的默认代码,所以谷歌代码中似乎有一个bug 应用程序只有在出现上述错误消息时才会崩溃Java 在android阵列适配器中使用notifyDataSetChanged时出错,java,android,android-listview,Java,Android,Android Listview,11-06 19:52:25.958:E/AndroidRuntime(29609): java.lang.IllegalStateException:适配器的内容已更改 已更改,但ListView未收到通知。确保 适配器的内容不是从后台线程修改的,而是 仅从UI线程。[在ListView中(-1,类 带有适配器(类)的android.widget.ListPopupWindow$DropDownListView) com.example.parkfoxxlight\u android.Plac
protected void publishResults(CharSequence constraint,
FilterResults results) {
if (results != null && results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
活动:
有没有办法解决这个问题?我在安卓4.3上。试试这个(只是一个猜测):
Filter
的performFiltering()
方法在后台线程上运行,您将从该方法更改适配器所基于的resultList
。如果您更改该数据列表,并且在此期间,ListView
访问适配器,它将看到某些内容在不知情的情况下发生了更改(它将不高兴)。您应该避免在performFiltering
方法中使用resultList
,只需创建一个新的临时列表:
// in the performFiltering method which runs on a background thread:
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
ArrayList<String> queryResults;
if (constraint != null && constraint.length() > 0) {
queryResults = autocomplete(constraint);
} else {
queryResults = new ArrayList<String>(); // empty list/no suggestions showing if there's no valid constraint
}
filterResults.values = queryResults;
filterResults.count = queryResults.size();
return filterResults; // ## Heading ##
}
private List<String> autocomplete(String input) {
// don't use the here the resultList List on which the adapter is based!
// some custom code to get items from http connection
ArrayList<String> queryResults = new ArrayList<String>(); // new list
queryResults.add("Some String");
return queryResults;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
// update the data with the new set of suggestions
resultList = (ArrayList<String>)results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
//在后台线程上运行的PerformFilter方法中:
@凌驾
受保护的筛选器结果性能筛选(CharSequence约束){
FilterResults FilterResults=新的FilterResults();
ArrayList查询结果;
if(constraint!=null&&constraint.length()>0){
queryResults=自动完成(约束);
}否则{
queryResults=new ArrayList();//空列表/没有显示是否存在有效约束的建议
}
filterResults.values=queryResults;
filterResults.count=queryResults.size();
返回filterResults;//##标题##
}
私有列表自动完成(字符串输入){
//不要使用适配器所基于的here-the-resultList列表!
//从http连接获取项目的一些自定义代码
ArrayList queryResults=新建ArrayList();//新建列表
添加(“一些字符串”);
返回查询结果;
}
@凌驾
受保护的void publishResults(CharSequence约束、FilterResults结果){
//使用新的建议集更新数据
resultList=(ArrayList)results.values;
如果(results.count>0){
notifyDataSetChanged();
}否则{
notifyDataSetionValidated();
}
}
它在哪一行代码上崩溃?顺便说一句,您正在将上下文转换为不安全的活动,并且在某些情况下肯定会导致崩溃。我想你可以用mHandler.post
替换act.runOnUiThread
,并在构造函数中创建你的处理程序。下面是日志:@Tenfour04 activity和context,不是一样吗?它们不是,否则你就不必强制转换了。活动是上下文的一个子类,因此,如果有人试图使用new PlacesAutoCompleteAdapter(getBaseContext())
(例如)实例化您的适配器,他们将在筛选器运行时获得ClassCastException方法在后台线程上运行,您可以从该方法更改适配器所基于的结果列表。如果您更改该列表,并且在此期间,ListView
访问适配器,它将看到某些内容在不知情的情况下发生了更改(它将不高兴)。检查这段代码。结果。值必须转换为(ArrayList)?已尝试,但自动完成不再工作Filter.publishResults将自动在ui线程上执行。我真的无法想象为什么我会遇到这么好的家伙!非常非常非常非常有帮助。难以置信……@Luksprog。。抱歉打扰了,我不想劫持这个帖子,但是你能看看这篇帖子吗。。它基于您的解决方案。。行if(constraint!=null | | constraint.length()=0){
将在约束等于null时导致NPE。if块应仅检查约束=null@luksprog短路是罪魁祸首。当约束为null时,constraint!=null
变为false,则or运算符将尝试计算约束。length()==0,从而导致NPE。我们需要的是if(constraint!=null&&constraint.length()>0)
。现在短路可以防止NPE@PurushothamanRamraj是的,我现在看到了,当时我愚蠢地混合了两个约束条件(不为null和不为空).好发现,我想知道为什么一直没有人对此发表评论。
@Override
public Filter getFilter() {
Filter filter = new Filter() {
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
if (constraint != null) {
ArrayList list = autocomplete(constraint.toString());
if (list != null) {
filterResults.values = list;
filterResults.count = list.size();
}
}
return filterResults;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
if (results != null && results.count > 0) {
//change the underlying data immediately before notifying UI
resultList = (ArrayList)results.values;
notifyDataSetChanged();
}
else {
notifyDataSetInvalidated();
}
}};
return filter;
}
// in the performFiltering method which runs on a background thread:
@Override
protected FilterResults performFiltering(CharSequence constraint) {
FilterResults filterResults = new FilterResults();
ArrayList<String> queryResults;
if (constraint != null && constraint.length() > 0) {
queryResults = autocomplete(constraint);
} else {
queryResults = new ArrayList<String>(); // empty list/no suggestions showing if there's no valid constraint
}
filterResults.values = queryResults;
filterResults.count = queryResults.size();
return filterResults; // ## Heading ##
}
private List<String> autocomplete(String input) {
// don't use the here the resultList List on which the adapter is based!
// some custom code to get items from http connection
ArrayList<String> queryResults = new ArrayList<String>(); // new list
queryResults.add("Some String");
return queryResults;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
// update the data with the new set of suggestions
resultList = (ArrayList<String>)results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}