2015-02-17 4 views
0

Добрый день, у меня есть следующий код, и я не могу понять, почему я получаю вышеуказанное сообщение об ошибке случайным образом. иногда я получаю это .. иногда я не делаю, но я бы хотел избавиться от него .. Я пробовал все (некоторые прокомментировали) и некоторые ответы здесь, но все еще возникают проблемы. может, ребята, любезно, пожалуйста, взгляните на него и скажите, где все пошло не так, потому что я не могу его заметить.AutocompleteTextView IllegalStateException: содержимое адаптера изменилось, но ListView не получил уведомление

public class SearchAutoCompleteAdapter extends BaseAdapter implements Filterable { 

    private ArrayList<BaseAutocompleteItems> resultList; 

    private LayoutInflater layoutInflater; 
    private Context context; 
    private int layout; 
    SearchAutoCompleteAPI searchautocomplete = new SearchAutoCompleteAPI(); //does API operation 



    public SearchAutoCompleteAdapter(Context context, int resource) { 
     super(); 
     this.context = context; 
     this.layout = resource; 
     this.resultList = new ArrayList<BaseAutocompleteItems>(); 
    } 


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


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


    @Override 
    public long getItemId(int position) { 
     return position; 
    } 



    @Override 
    public View getView(int position, View convertView, ViewGroup parent) { 

     if (convertView == null) { 
      layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      convertView = layoutInflater.inflate(layout, null); 

     } 

     TextView name = (TextView) convertView.findViewById(R.id.suggestion_text_id); 
     TextView category = (TextView) convertView.findViewById(R.id.suggestion_category_text_id); 

     name.setText(resultList.get(position).getName()); 
     category.setText(resultList.get(position).getCategoryName()); 

     return convertView; 
    } 



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

       FilterResults filterResults = new FilterResults(); 
       List<BaseAutocompleteItems> tempfilteredProducts; 


       //synchronized (filterResults) { 

        if (constraint != null || constraint.length() == 0) { 
         Log.d(SearchogHomeActivity.TAG, "characters in constraints is not null"); 


         tempfilteredProducts = searchautocomplete.autocomplete(constraint.toString()); 

        } else { 

         tempfilteredProducts = new ArrayList<BaseAutocompleteItems>(); 
        } 

        filterResults.values = tempfilteredProducts; 
        filterResults.count = tempfilteredProducts.size(); 

        return filterResults; 

       //} 
      } 



      @Override 
      protected void publishResults (CharSequence constraint, final FilterResults results){ 

       //synchronized (results) { 
        resultList = (ArrayList<BaseAutocompleteItems>) results.values; 
        if (results != null && results.count > 0) { 

         notifyDataSetChanged(); 

        } else { 

         notifyDataSetInvalidated(); 
        } 

       } 
      // } 
     }; 

     return filter; 
    } 

} 

И это, где я использую его в своей деятельности:

@Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_category); 


     textEdit = (AutoCompleteTextView)findViewById(R.id.search_autocomplete_id); 
     adapter = new SearchAutoCompleteAdapter(this, R.layout.autocomplete_list); 
     textEdit.setText(""); 
     //textEdit.setThreshold(0); 
     textEdit.setOnItemClickListener(this); 
     textEdit.setAdapter(adapter); 

и вот мой журнал по запросу:

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.Example.searchAdapter.adapter.SearchAutoCompleteAdapter)] 
      at android.widget.ListView.layoutChildren(ListView.java:1562) 
      at android.widget.AbsListView.onLayout(AbsListView.java:2148) 
      at android.view.View.layout(View.java:15596) 
      at android.view.ViewGroup.layout(ViewGroup.java:4966) 
      at android.widget.FrameLayout.layoutChildren(FrameLayout.java:573) 
      at android.widget.FrameLayout.onLayout(FrameLayout.java:508) 
      at android.view.View.layout(View.java:15596) 
      at android.view.ViewGroup.layout(ViewGroup.java:4966) 
      at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:2072) 
      at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1829) 
      at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1054) 
      at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5779) 
      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:5221) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:372) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 

API вызова:

public ArrayList<BaseAutocompleteItems> autocomplete(String s){ 

     //final ArrayList<BaseAutocompleteItems> myresultList = new ArrayList<BaseAutocompleteItems>(); 
     //myresultList.clear(); 
     String input = BASE_AUTOCOMPLETE_URL + s; 

     Log.d(SearchActivity.TAG, "AutoComplete string is " + input); 
     SearchRestClient.get(input, null, new JsonHttpResponseHandler(){ 

      @Override 
      public void onSuccess(int statusCode, Header[] headers, JSONObject response) { 
       super.onSuccess(statusCode, headers, response); 
      } 

      @Override 
      public void onSuccess(int statusCode, Header[] headers, JSONArray response) { 
       super.onSuccess(statusCode, headers, response); 
       ObjectMapper objectmapper = new ObjectMapper(); 
       objectmapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); 
       try { 
       //1 
       //List<BaseAutocompleteItems> autocompleteItems = objectmapper.readValue(String.valueOf(response), objectmapper.getTypeFactory().constructCollectionType(ArrayList.class, BaseAutocompleteItems.class)); 

        myresultList = objectmapper.readValue(String.valueOf(response), objectmapper.getTypeFactory().constructCollectionType(ArrayList.class, BaseAutocompleteItems.class)); 

         //2 
        /* myresultList.clear(); 
        for(BaseAutocompleteItems items: autocompleteItems){ 
         myresultList.add(items); 
        }*/ 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 


      } 

      @Override 
      public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONObject errorResponse) { 
       super.onFailure(statusCode, headers, throwable, errorResponse); 
      } 

      @Override 
      public void onFailure(int statusCode, Header[] headers, Throwable throwable, JSONArray errorResponse) { 
       super.onFailure(statusCode, headers, throwable, errorResponse); 
      } 
     }); 

     Log.d(SearchActivity.TAG, "size in adapter is " + myresultList.size()); 
     return myresultList; 

    } 
+0

Почему вы используете TextWatcher? – Luksprog

+0

Опубликовать свой файл журнала? – Josef

+0

@Luksprog извините за очень поздний ответ, я опубликовал это, когда вчера закрывался от работы. я использовал его изначально, чтобы получить счет персонажа до того, как APi был вызван, но затем я остановился. я удалю его из кода сейчас, но все тот же вопрос. я включил журнал. Спасибо – irobotxxx

ответ

1

Вот метод getFilter: он работает нормально

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


        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(); 
         } 
        } 
       }); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 
    return filter; 
} 


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


    HttpURLConnection conn = null; 
    StringBuilder jsonResults = new StringBuilder(); 
    try { 
     StringBuilder sb = new StringBuilder(Constant.PLACES_API_BASE + Constant.TYPE_AUTOCOMPLETE + Constant.OUT_JSON); 
     sb.append("?key=AIzaSyAlU5QFZWbgInmPlV-LWFlXiRS7pZ8wD8o"); 
     //sb.append("&components=country:au"); 
     //sb.append("&location=" + String.valueOf(LocationHelperService.dblLatitude) + "," + String.valueOf(LocationHelperService.dblLongitude)); 
     sb.append("&input=" + URLEncoder.encode(input, "utf8")); 
     sb.append("&radius=" + String.valueOf(50)); 

     URL url = new URL(sb.toString()); 

     System.out.println("URL: " + url); 
     conn = (HttpURLConnection) url.openConnection(); 
     InputStreamReader in = new InputStreamReader(conn.getInputStream()); 

     // 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", 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 
     JSONObject jsonObj = new JSONObject(jsonResults.toString()); 
     JSONArray predsJsonArray = jsonObj.getJSONArray("predictions"); 

     // Extract the Place descriptions from the results 
     resultList = new ArrayList<String>(predsJsonArray.length()); 
     mainTextList=new ArrayList<String>(predsJsonArray.length()); 
     secondoryTextList=new ArrayList<String>(predsJsonArray.length()); 


     for (int i = 0; i < predsJsonArray.length(); i++) { 
      System.out.println(predsJsonArray.getJSONObject(i).getString("description")); 
      System.out.println("============================================================"); 
      resultList.add(predsJsonArray.getJSONObject(i).getString("description")); 
      mainTextList.add(predsJsonArray.getJSONObject(i).getJSONObject("structured_formatting").getString("main_text")); 

      if(predsJsonArray.getJSONObject(i).getJSONObject("structured_formatting").has("secondary_text")) 
      { 
       secondoryTextList.add(predsJsonArray.getJSONObject(i).getJSONObject("structured_formatting").getString("secondary_text")); 
      } 
      else{ 
       secondoryTextList.add(""); 
      } 




     } 
    } catch (JSONException e) { 
     Log.e(LOG_TAG, "Cannot process JSON results", e); 
    } 

    return resultList; 
} 
+0

Это действительно нехорошее решение. Есть причина, почему функция performFiltering помещается в фоновый поток, и это связано с тем, что это может потребовать выполнения дополнительной работы, которую вы не хотите делать в потоке пользовательского интерфейса. И вы просто помещаете работу обратно в поток пользовательского интерфейса здесь. – Bilthon

+0

да, я знаю это, но когда я меняю контент в адаптере и уведомляю его несколько раз, адаптер не меняет нити ui, потому что он находится в фоновом режиме, поэтому для воздействия на контент мне нужно поместить результат фильтрации в поток ui. – khushbu

+0

Если у вас есть какое-либо другое предложение, чем сообщите мне, я буду применять его. – khushbu

0

Я решил эту проблему после много исследований и отладки. Вы можете воспользоваться здесь here

Смежные вопросы

 Смежные вопросы