2016-04-27 2 views
0

ich folgende Fehlerbericht immer bin:Illegal in PlaceAutocompleteAdapter für Google Places API

Fatal Exception: 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. [in ListView(-1, class android.widget.ListPopupWindow$DropDownListView) with Adapter(class com.galleri5.android.adapters.PlaceAutocompleteAdapter)] 
     at android.widget.ListView.layoutChildren(ListView.java:1562) 
     at android.widget.AbsListView.onLayout(AbsListView.java:2151) 
     at android.view.View.layout(View.java:15689) 
     at android.view.ViewGroup.layout(ViewGroup.java:5040) 
     at android.widget.FrameLayout.layoutChildren(FrameLayout.java:579) 
     at android.widget.FrameLayout.onLayout(FrameLayout.java:514) 
     at android.view.View.layout(View.java:15689) 
     at android.view.ViewGroup.layout(ViewGroup.java:5040) 
     at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2116) 
     at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1873) 
     at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1084) 
     at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5990) 
     at android.view.Choreographer$CallbackRecord.run(Choreographer.java:767) 
     at android.view.Choreographer.doCallbacks(Choreographer.java:580) 
     at android.view.Choreographer.doFrame(Choreographer.java:550) 
     at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:753) 
     at android.os.Handler.handleCallback(Handler.java:739) 
     at android.os.Handler.dispatchMessage(Handler.java:95) 
     at android.os.Looper.loop(Looper.java:135) 
     at android.app.ActivityThread.main(ActivityThread.java:5343) 
     at java.lang.reflect.Method.invoke(Method.java) 
     at java.lang.reflect.Method.invoke(Method.java:372) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:905) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:700) 

Und hier ist mein PlaceAutoCompleteAdapter:

public class PlaceAutocompleteAdapter 
     extends ArrayAdapter<AutocompletePrediction> implements Filterable { 
    protected final String TAG = getClass().getSimpleName(); 
    private static final CharacterStyle STYLE_BOLD = new StyleSpan(Typeface.BOLD); 
    private ArrayList<AutocompletePrediction> mResultList; 
    private GoogleApiClient mGoogleApiClient; 
    private LatLngBounds mBounds; 
    private AutocompleteFilter mPlaceFilter; 

    public PlaceAutocompleteAdapter(Context context, GoogleApiClient googleApiClient, 
            LatLngBounds bounds, AutocompleteFilter filter) { 
     super(context, android.R.layout.simple_expandable_list_item_2, android.R.id.text1); 
     mGoogleApiClient = googleApiClient; 
     mBounds = bounds; 
     mPlaceFilter = filter; 
    } 

    public void setBounds(LatLngBounds bounds) { 
     mBounds = bounds; 
    } 

    @Override 
    public int getCount() { 
     return mResultList != null ? mResultList.size() : 0; 
    } 

    @Override 
    public AutocompletePrediction getItem(int position) { 
     return position < mResultList.size() ? mResultList.get(position) : null; 
    } 

    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 
     View row = super.getView(position, convertView, parent); 

     // Sets the primary and secondary text for a row. 
     // Note that getPrimaryText() and getSecondaryText() return a CharSequence that may contain 
     // styling based on the given CharacterStyle. 

     AutocompletePrediction item = getItem(position); 
     if((item != null) && (row != null)) { 
      row.setBackgroundColor(Color.parseColor("#707070")); 
      TextView textView1 = (TextView) row.findViewById(android.R.id.text1); 
      textView1.setTextSize(14); 
      TextView textView2 = (TextView) row.findViewById(android.R.id.text2); 
      textView2.setTextSize(12); 
      textView1.setText(item.getPrimaryText(STYLE_BOLD)); 
      textView2.setText(item.getSecondaryText(STYLE_BOLD)); 
     } 

     return row; 
    } 

    /** 
    * Returns the filter for the current set of autocomplete results. 
    */ 
    @Override 
    public Filter getFilter() { 
     return new Filter() { 
      @Override 
      protected FilterResults performFiltering(CharSequence constraint) { 
       FilterResults results = new FilterResults(); 
       // Skip the autocomplete query if no constraints are given. 
       if (constraint != null) { 
        // Query the autocomplete API for the (constraint) search string. 
        mResultList = getAutocomplete(constraint); 
        if ((mResultList != null) && (!mResultList.isEmpty())) { 
         // The API successfully returned results. 
         results.values = mResultList; 
         results.count = mResultList.size(); 
        } 
       } 
       return results; 
      } 

      @Override 
      protected void publishResults(CharSequence constraint, FilterResults results) { 
       if (results != null) { 
        // The API returned at least one result, update the data. 
        if (results.count > 0) { 
         notifyDataSetChanged(); 
        } 
       } else { 
        // The API did not return any results, invalidate the data set. 
        notifyDataSetInvalidated(); 
       } 
      } 

      @Override 
      public CharSequence convertResultToString(Object resultValue) { 
       // Override this method to display a readable result in the AutocompleteTextView 
       // when clicked. 
       if (resultValue instanceof AutocompletePrediction) { 
        return ((AutocompletePrediction) resultValue).getFullText(null); 
       } else { 
        return super.convertResultToString(resultValue); 
       } 
      } 
     }; 
    } 

    private ArrayList<AutocompletePrediction> getAutocomplete(CharSequence constraint) { 
     if (mGoogleApiClient.isConnected()) { 

      // Submit the query to the autocomplete API and retrieve a PendingResult that will 
      // contain the results when the query completes. 
      PendingResult<AutocompletePredictionBuffer> results = 
        Places.GeoDataApi 
          .getAutocompletePredictions(mGoogleApiClient, constraint.toString(), 
            mBounds, mPlaceFilter); 

      // This method should have been called off the main UI thread. Block and wait for at most 60s 
      // for a result from the API. 
      AutocompletePredictionBuffer autocompletePredictions = results 
        .await(60, TimeUnit.SECONDS); 

      // Confirm that the query completed successfully, otherwise return null 
      final Status status = autocompletePredictions.getStatus(); 
      if (!status.isSuccess()) { 
       Toast.makeText(getContext(), "Error contacting API: " + status.toString(), 
         Toast.LENGTH_SHORT).show(); 
       autocompletePredictions.release(); 
       return null; 
      } 

      // Freeze the results immutable representation that can be stored safely. 
      return DataBufferUtils.freezeAndClose(autocompletePredictions); 
     } 
     return null; 
    } 
} 

Dieser Code aus dem Google-Orte api zur automatischen Vervollständigung Probe genommen wird. Ich änderte es für UI-Änderungen anders, mehr oder weniger es ist dasselbe. Ich kann nicht herausfinden, wie dieser Unfall passiert ist und was könnte Grund dafür sein? Jede Hilfe würde sehr geschätzt werden.

bearbeiten: Hier sind die relevanten Teile der Aktivität, wo ich den Adapter am Einstellung:

@Bind(R.id.loc) 
    AutoCompleteTextView loc; 
protected GoogleApiClient mGoogleApiClient; 

    private PlaceAutocompleteAdapter mAdapter; 

    private static final LatLngBounds BOUNDS_GREATER_SYDNEY = new LatLngBounds(
      new LatLng(-34.041458, 150.790100), new LatLng(-33.682247, 151.383362)); 

@Override 
onCreate() { 
mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .enableAutoManage(this, 0 /* clientId */, this) 
       .addApi(Places.GEO_DATA_API) 
       .build(); 

loc.setOnItemClickListener(mAutocompleteClickListener); 
     mAdapter = new PlaceAutocompleteAdapter(this, mGoogleApiClient, BOUNDS_GREATER_SYDNEY, null); 
     loc.setAdapter(mAdapter); 
} 
+0

Postklasse, in dem Sie setzen Adapter –

+0

@VivekMishra bitte die Bearbeitung sehen. –

+0

welche Version von Android verwenden Sie. – USKMobility

Antwort

1

Nach Ausnahme, ändern Sie die Liste Inhalt in einem anderen Thread. Um das Problem zu lösen, müssen Sie den Inhalt von arraylist im UI-Thread ändern. Von doc performFiltering-Methode wird in verschiedenen Thread ausgeführt. Um das Problem zu beheben, fügen Sie arraylist in der publishResults-Methode Inhalt hinzu und rufen notifydatasetchange auf.

Andere Lösung: Update performfiltering wie folgt:

protected FilterResults performFiltering(CharSequence constraint) { 
       FilterResults results = new FilterResults(); 
       // Skip the autocomplete query if no constraints are given. 
       if (constraint != null) { 
        final ArrayList<AutocompletePrediction> mResultList1 = getAutocomplete(constraint); 

((Activity)mContext).runOnUiThread(new Runnable() { 
      public void run() { 

        if ((mResultList1 != null) && (!mResultList1.isEmpty())) { 
         // The API successfully returned results. 
         results.values = mResultList1; 
         results.count = mResultList1.size(); 
          mResultList.clear(); 
          mResultList.addAll(mResultList1); 
        } 
      } 
     }); 
       } 
       return results; 
      } 

For reference

+0

Danke. Ich werde das versuchen. Aber da ich dieses Problem nicht reproduzieren kann, hoffe ich nur, dass es funktioniert. –