Question

I've been receiving a few Play Store reports of my android app crashing due to IllegalStateException in my AutoCompleteTextView. However, I've never been able to recreate the issue myself. The AutoCompleteTextView uses custom filtering, and I more or less followed the codes here: Custom filtering in AutoCompleteTextView not working

I've done some research on the problem, found this as one of the results: How to resolve "The content of the adapter has changed but ListView did not receive a notification” exception but still can't work out what's wrong with my code. I can't even figure out what's causing the exception to occur, it just occurs randomly, though most of the time it doesn't occur. What's more frustrating, the exception stack trace doesn't point out which line of my code that is causing the exception.

Here is the exception stack trace:

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 transponders.transmob.JourneyPlanner$LocationAdapter)]
at android.widget.ListView.layoutChildren(ListView.java:1541)
at android.widget.AbsListView.onLayout(AbsListView.java:1428)
at android.view.View.layout(View.java:7228)
at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
at android.view.View.layout(View.java:7228)
at android.view.ViewRoot.performTraversals(ViewRoot.java:1148)
at android.view.ViewRoot.handleMessage(ViewRoot.java:1868)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:130)
at android.app.ActivityThread.main(ActivityThread.java:3691)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:907)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:665)
at dalvik.system.NativeStart.main(Native Method)

And here is my custom filter code in the custom adapter class:

        @Override
        public Filter getFilter() 
        {
            Filter filter = new Filter(){
                  @Override
                  protected FilterResults performFiltering(CharSequence constraint)
                  {
                      locations.clear();
                      FilterResults results = new FilterResults();
                      String typedText = ownerACTV.getText().toString();

                      try
                      {
                          Log.d("performFiltering", "TYPED TEXT LENGTH: " + typedText.length());
                          if(!typedText.equals("Current location"))
                          {
                              String url = "some URL";
                              request = new JSONRequest();
                              request.setListener(JourneyPlanner.this);
                              request.execute(url);

                              String result = request.get();

                              Object obj = JSONValue.parse(result);
                              JSONArray array = (JSONArray)((JSONObject)obj).get("Locations");

                              for(int i = 0; i < array.size(); i++)
                              {
                                  JSONObject location = (JSONObject) array.get(i);
                                  String desc = (String) location.get("Description");
                                  String id = (String) location.get("Id");

                                  Log.d("filterResults", "Description: " + desc);
                                  Log.d("filterResults", "ID: " + id);

                                  String[] splitted = desc.split(" \\(");
                                  if (splitted.length > 1)
                                      desc = splitted[0];

                                  locationsToID.put(desc, id);
                                  locations.add(desc);
                              }
                          }

                          results.values = locations;
                          results.count = locations.size();

                      }
                      catch (Exception e)
                      {
                          e.printStackTrace();
                      }

                      Log.d("performFiltering", "return FilterResults");
                      return results;
                  }

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

            return filter;
        }

I can give you other parts of the code as well if necessary. I have to make a call to the web in order to populate the autocomplete drop down list, I'm guessing that it may be the one causing the exception?

Was it helpful?

Solution

the problem is your "locations" field that you modify in non ui thread (perfornFiltering method), you should use FilterResults which is passed to publishResults

OTHER TIPS

Here is the getFilter method:which is working fine

 @Override
 public Filter getFilter() {
 Filter filter = new Filter() {
    @Override
    protected FilterResults performFiltering(final CharSequence  constraint) {
        final FilterResults filterResults = new FilterResults();

       activity.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                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, final     FilterResults results) {
        try {
           activity.runOnUiThread(new Runnable() {
               @Override
               public void run() {
                   if (results != null && results.count > 0) {

                      // resultList=(ArrayList<String>)results.values;
                       notifyDataSetChanged();
                   } else {
                       notifyDataSetInvalidated();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top