【问题标题】:AutocompleteTextView Error: IllegalStateException: The content of the adapter has changed but ListView did not receive a notificationAutocompleteTextView 错误:IllegalStateException:适配器的内容已更改但 ListView 未收到通知
【发布时间】:2014-09-11 13:13:16
【问题描述】:

在我的 AutocompleteTextView 上取消或快速键入时,我在此类中遇到 IllegalStateException 错误。我已经阅读了一些关于此的内容,但我无法解决这个问题。 任何人都可以更正我的代码吗?

感谢任何帮助! (对不起我的英语不好)

这是完整的错误:

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.ListPopupWindow$DropDownListView) with Adapter(class com.turkeys.planandgo.Activity.MapActivity$AutoComplete)]

这是我的课:

public class AutoComplete extends ArrayAdapter<String> implements Filterable {
    private static final String LOG_TAG = "carEgiri";

    private static final String PLACES_API_BASE = "https://maps.googleapis.com/maps/api/place";
    private static final String TYPE_AUTOCOMPLETE = "/autocomplete";
    private static final String OUT_JSON = "/json";

    private static final String API_KEY = "AIzaSyCDycjwe51YuMe7Sx8nHv9Z6C-kBGPEQ64";

    private ArrayList<String> resultList;

    private ArrayList<String> autocomplete(String input) {
            ArrayList<String> resultList = null;

            HttpURLConnection conn = null;
            StringBuilder jsonResults = new StringBuilder();
            try {
                StringBuilder sb = new StringBuilder(PLACES_API_BASE + TYPE_AUTOCOMPLETE + OUT_JSON);
                sb.append("?sensor=false&key=" + API_KEY);
                sb.append("&input=" + URLEncoder.encode(input, "utf8"));

                URL url = new URL(sb.toString());
                conn = (HttpURLConnection) url.openConnection();
                InputStreamReader in = new InputStreamReader(conn.getInputStream());
                Log.d("====", "Requesst send");
                // Load the results into a StringBuilder
                int read;
                char[] buff = new char[1024];
                while ((read = in.read(buff)) != -1) {
                    jsonResults.append(buff, 0, read);
                }
            } catch (MalformedURLException e) {
                Log.e(LOG_TAG, "Error processing Places API URL", e);
                return resultList;
            } catch (IOException e) {
                Log.e(LOG_TAG, "Error connecting to Places API", e);
                return resultList;
            } finally {
                if (conn != null) {
                    conn.disconnect();
                }
            }

            try {
                // Create a JSON object hierarchy from the results
                Log.d("JSON","Parsing resultant JSON :)");
                JSONObject jsonObj = new JSONObject(jsonResults.toString());
                JSONArray predsJsonArray = jsonObj.getJSONArray("predictions");

                // Extract the Place descriptions from the results
                resultList = new ArrayList<String>(predsJsonArray.length());
                Log.d("JSON","predsJsonArray has length " + predsJsonArray.length());
                for (int i = 0; i < predsJsonArray.length(); i++) {

                    resultList.add(predsJsonArray.getJSONObject(i).getString("description"));
                    Log.d("JSON",resultList.get(i));
                }
            } catch (JSONException e) {
                Log.e(LOG_TAG, "Cannot process JSON results", e);
            }

            return resultList;
        }

    public AutoComplete(Context context, int textViewResourceId) {
        super((Context) context, textViewResourceId);
    }

    @Override
    public int getCount() {
        if (resultList == null)
            return 0;
        return resultList.size();
    }

    @Override
    public String getItem(int index) {
        return resultList.get(index);
    }

    @Override
    public Filter getFilter() {
        Filter filter = new Filter() {
                @Override
                protected FilterResults performFiltering(CharSequence constraint) {
                    FilterResults filterResults = new FilterResults();
                    if (constraint != null) {
                        // Retrieve the autocomplete results.
                        resultList = autocomplete(constraint.toString());

                        // Assign the data to the FilterResults
                        filterResults.values = resultList;
                        filterResults.count = resultList.size();
                    }
                    return filterResults;
                }

                @Override
                protected void publishResults(CharSequence constraint,FilterResults results) {
                    if (results != null && results.count > 0) {
                        notifyDataSetChanged();
                    } else {
                        notifyDataSetInvalidated();
                    }
                }
        };
        return filter;
    }

}

【问题讨论】:

  • 你使用什么线程,为什么?
  • 一般在应用程序中?现在我也得到这个错误: java.lang.IndexOutOfBoundsException: Invalid index 3, size is 3 in this line: return resultList.get(index);
  • 在您的 AutoCompleteTextView 内容中
  • 发布的代码是我唯一使用的 AutocompleteTextView 以及 setAdapter() 方法..
  • 好的,为什么要使用自定义过滤器,现有的还不够?

标签: android autocompletetextview illegalstateexception


【解决方案1】:

请从performFiltering 方法中删除 resultList。 performFiltering 方法在后台线程中运行。 here信息更清晰!

【讨论】:

    【解决方案2】:

    我遇到了同样的问题,经过大量调试和研究后,我通过重写 notifyDataSetChanged() 并评估了建议列表的大小解决了我的问题。它可能会帮助某人。代码sn-p如下:

    private int size = 0; 
    
    @Override
    public void notifyDataSetChanged() {
          size = suggestionList.size();
          super.notifyDataSetChanged();
    }
    

    并将 getCount() 中的大小返回为:

    @Override
    public int getCount() {
    
       return size; // Return the size of the suggestions list.
    }
    

    My Case(Application) 中的自定义过滤器如下:

    private class CustomFilter extends Filter {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                suggestions.clear();
                FilterResults filterResults = new FilterResults();
                try {
    
                        if (originalList != null && constraint != null) { // Check if the Original List and Constraint aren't null.
                            try {
                                for (int i = 0; i < originalList.size(); i++) {
                                    // if (originalList.get(i).toLowerCase().contains(constraint)) {
                                    if (originalList.get(i).toLowerCase().contains(constraint.toString().toLowerCase())) {
                                        suggestionList.add(originalList.get(i)); // If TRUE add item in Suggestions.
                                    }
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        } else {
                            notifyDataSetChanged();
                        }
    
                } catch (Exception e) {
                    e.printStackTrace();
                }
               // Create new Filter Results and return this to publishResults;
                filterResults.values = suggestionList;
                filterResults.count = suggestionList.size();
    
                return filterResults;
            }
    
            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
               if (results != null && results.count > 0) {
                    notifyDataSetChanged();
                } else {
                    notifyDataSetInvalidated();
                }
            }
        }
    

    【讨论】:

      【解决方案3】:

      遇到同样的问题 我做了一些改变来解决它: 1) 不要在 performFiltering(...) 方法中对数据集进行任何更改
      2) 仅在 publishResults(...) 方法中进行更改

      所以我们制作了类似的东西:

      //suggestions dataset
      ArrayList<Item> suggestions = new ArrayList<>();
      

      在过滤器中

      @Override
          protected void publishResults(CharSequence constraint, FilterResults results) {
             if (results != null && results.count > 0) {
                  // rewrite array or clear it and fill new items in it
                  suggestions = (ArrayList<Item>)results.values
                  notifyDataSetChanged();
              }
          }
      

      并且在 getCount() 方法中的适配器中返回建议大小:

      @Override
      public int getCount() {
          return suggestions.size();
      }
      

      【讨论】:

        【解决方案4】:

        在响应网络调用方法时添加 notifyDataSetChanged()

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-09-22
          • 2011-03-09
          • 1970-01-01
          • 2014-12-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多