Search code examples
androidlistviewandroid-asynctaskandroid-adapteruniversal-image-loader

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification - List with Universal Image Loader


I am trying to update a fragment with list view once the Async call is complete but I am getting the following error :

java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification.

I am updating the adapter onPostExecute and have also checked the function is running on main thread but still I am getting the IllegalStateException.

@Override
    protected void onPostExecute(List<String> result) {
        if (null != mClient)
            mClient.close();
        //TODO
            //Constants.IMAGES = result.toArray(new String[result.size()]);
        Constants.IMAGES.addAll(result);
            Log.i("IMAGES", IMAGES.toString());
            if (mTheListener != null && firstCallFlag ) {
                firstCallFlag = false;
                mTheListener.GotoNextScreen();
            }else{
                dataUpdateListener.dataUpdated(result);
            }
    }

@Override
    protected List<String> doInBackground(Void... params) {

        if(afterTag != null){
            URL += "?after="+afterTag;
            System.out.println("::New URL:: "+ URL);
        }
        HttpGet request = new HttpGet(URL);
        JSONResponseHandler responseHandler = new JSONResponseHandler();
        try {
            return mClient.execute(request, responseHandler);
        } catch (ClientProtocolException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }


@Override
public void dataUpdated(List<String> data) {
    // TODO Auto-generated method stub
    System.out.println("::Notify data update listener called");
    System.out.println("Looper "+Looper.myLooper());
    System.out.println("Main Looper "+Looper.getMainLooper());
    imageUrls.addAll(data);
    mAdapter.notifyDataSetChanged();
}

//Fragment onCreateView - Adapter is set here

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fr_image_list, container,
            false);
    listView = (ListView) rootView.findViewById(android.R.id.list);

    // Adding the load more

    // LoadMore button
    Button btnLoadMore = new Button(getActivity().getApplicationContext());
    btnLoadMore.setText("Load More");

    // Adding Load More button to lisview at bottom
    listView.addFooterView(btnLoadMore);

    /**
     * Listening to Load More button click event
     * */
    btnLoadMore.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View arg0) {
            // Starting a new async task
            Constants.getUrlFromRedditService();
        }
    });
    mAdapter = new ImageAdapter();
    ((ListView) listView).setAdapter(new ImageAdapter());

    listView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
            startImagePagerActivity(position);
        }
    });
    return rootView;
}

P.S: I am using Universal Image Loader to populate images on the list .


Solution

  • try replacing the below line of code

     ((ListView) listView).setAdapter(new ImageAdapter());
    

    with

     ((ListView) listView).setAdapter(mAdapter);
    

    See that for the listView you are always setting a new adapter and in your onPostExecute you are notifying to a different instance of adapter