"java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive notification" On an AutoCompleteTextView

0

Currently I have a form in which I have a AutoCompleteTextView element, to fill this View I have an adapter called AutoCompleteStoreAdapter in which, using the getFilter () method, I get the data from the GetAllStores class that extends from AsynkTask , this is because the data to fill the AutoCompleteTextView is obtained from a web service from whatever they write in the field.

I notice that when I start writing there is a slight delay between what I write and the list. When I write very fast, I erase the writing, I write something else, I delete it again and so on (to see the behavior of my field due to the delay it has), after doing this a few times, it throws me the following 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.DropDownListView) with Adapter(class mx.circuloinformador.qr.adapters.AutoCompleteStoreAdapter)]

I understand that I must notify the adapter of the changes with notifyDataSetChanged () but in this case, it loads the data asynchronously and only happens when I write and changed the AutoCompleteTextView content very fast, I can not find where could I call notifyDataSetChanged () and avoid the error.

AutoCompleteStoreAdapter

public class AutoCompleteStoreAdapter extends ArrayAdapter implements Filterable {
    private ArrayList<Store> stores;
    private AutoCompleteStoreAdapter adapter;

    public AutoCompleteStoreAdapter(Context context, int resource) {
        super(context, resource);
        stores = new ArrayList<Store>();
        adapter = this;
    }

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

    @Override
    public Store getItem(int position) {
        return stores.get(position);
    }

    @Override
    public Filter getFilter() {
        Filter myFilter = new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence constraint) {
                FilterResults filterResults = new FilterResults();
                if(constraint != null){
                    try{
                        String term = constraint.toString();
                        stores = new GetAllStores(adapter).execute(term).get();
                    } catch (NullPointerException e) {
                        stores = new ArrayList<Store>();
                        stores.add(new Store(0, "No válido", "No válido", 0, false, false));
                        notifyDataSetChanged();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }

                    try {
                        filterResults.values = stores;
                        filterResults.count = stores.size();
                    } catch (NullPointerException e) {
                        stores = new ArrayList<Store>();
                        stores.add(new Store(0, "No válido", "No válido", 0, false, false));
                        filterResults.values = stores;
                        filterResults.count = stores.size();
                        notifyDataSetChanged();
                    }
                }
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence constraint, FilterResults results) {
                if(results != null && results.count > 0){
                    notifyDataSetChanged();
                }else{
                    try {
                        notifyDataSetInvalidated();
                    } catch (NullPointerException e) {
                        stores = new ArrayList<Store>();
                        stores.add(new Store(0, "No válido", "No válido", 0, false, false));
                        notifyDataSetChanged();
                    }
                }
            }
        };

        return myFilter;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        LayoutInflater inflater = LayoutInflater.from(getContext());
        View view = inflater.inflate(R.layout.auto_complete_stores_layout, parent, false);

        Store store;
        try {
            store = stores.get(position);
        } catch (IndexOutOfBoundsException e) {
            store = stores.get(stores.size() - 1);
            Log.e("[CI]", e.getMessage());
        }

        TextView storeName = (TextView) view.findViewById(R.id.lblStoreName);
        storeName.setText(store.getName().toUpperCase());

        return view;
    }
}

GetAllStores

private class GetAllStores extends AsyncTask<String, String, ArrayList> {

        private AutoCompleteStoreAdapter adapter;

        public GetAllStores(AutoCompleteStoreAdapter adapter) {
            this.adapter = adapter;
        }

        @Override
        protected ArrayList<Store> doInBackground(String... strings) {
            ArrayList<Store> stores = Store.getAllStoresByName(strings[0]);
            return stores;
        }

        @Override
        protected void onPostExecute(ArrayList arrayList) {
            Log.i("[CI]", "Se descargaron todos los extablecimientos");
            this.adapter.notifyDataSetChanged();
        }
    }

Store.getAllStoresByName (strings [0]); only gets the data from a web service, so I do not think it necessary to put the code as well.

    
asked by Vicente Gutiérrez 13.03.2018 в 20:07
source

0 answers