Search code examples
androidandroid-viewpagerandroid-volley

Notify data change to viewPagerAdapter


I load images from server in recyvlerview with infinite scroll. I set onClick on recyclerview Itee, it open in viewpager. It works fine but when i load from server in infinite load, it gave error -

 java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 9, found: 29 .

Volley response

     @Override
                public void onResponse(JSONObject response) {
                    progressBarBottom.setVisibility(View.GONE);

                    imagelist = new ArrayList<>();
                    JSONArray heroArray = null;


                    try {
                        heroArray = response.getJSONArray("images");
                        for (int i = 0; i < heroArray.length(); i++) {
                            JSONObject jsonObject = 
                        heroArray.getJSONObject(i);

                            Photos photos = new Photos();
                            photos.setUrl(jsonObject.getString("image"));

                            imagelist.add(photos);

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


                    adapter.addImages(imagelist);
                    myViewPagerAdapter.addImages(imagelist);
                    adapter.notifyDataSetChanged();
                    myViewPagerAdapter.notifyDataSetChanged();
                }

I Created a modal class, that get data from server and set data. Photos Class

@Parcel
public class Photos {
public String url;
public String title;

public Photos() {

}

 public Photos(String url, String weight, String title, String thumb, String 
 date, String hit) {
    this.url = url;
    this.thumb = thumb;
}

public String getUrl() {
    return url;
}

public void setUrl(String url) {
    this.url = url;
}



public String getThumb() {
    return thumb;
}

public void setThumb(String thumb) {
    this.thumb = thumb;
}

}

MyViewPagerAdapter

public class MyViewPagerAdapter extends PagerAdapter {
private Context context;

ProgressBar fullImagePB;
private ArrayList<Photos> imagesList;
private LayoutInflater layoutInflater;

public MyViewPagerAdapter(Context context, ArrayList<Photos> imagesList) {
    this.context = context;
    this.imagesList = imagesList;
    layoutInflater = (LayoutInflater) 
 context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

}

@Override
public Object instantiateItem(final ViewGroup container, int position) {
    layoutInflater = (LayoutInflater) 
  context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    Photos image = imagesList.get(position);
    final View view = 
  layoutInflater.inflate(R.layout.image_fullscreen_preview, container, 
  false);
    fullImagePB = view.findViewById(R.id.fullImagePB);
    final ImageView imageViewPreview = (ImageView) 
  view.findViewById(R.id.image_preview);
    imageViewPreview.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
        }
    });
    imageViewPreview.setOnTouchListener(new 
   ImageMatrixTouchHandler(view.getContext()));


    Glide.with(imageViewPreview.getContext())
            .load(image.getUrl())
            .asBitmap()
            .listener(new RequestListener<String, Bitmap>() {
                @Override
                public boolean onException(Exception e, String model, 
  Target<Bitmap> target, boolean isFirstResource) {
                    return false;
                }

                @Override
                public boolean onResourceReady(Bitmap resource, String model, 
  Target<Bitmap> target, boolean isFromMemoryCache, boolean isFirstResource) 
   {

                    fullImagePB.setVisibility(View.GONE);
                    return false;
                }
            })
            .fitCenter().into(new SimpleTarget<Bitmap>() {
        @Override
        public void onResourceReady(final Bitmap resource, GlideAnimation<? 
   super Bitmap> glideAnimation) {
            imageViewPreview.setImageBitmap(resource);

        }

    });
    imageViewPreview.setTag(position);

    container.addView(view);
    return view;

}

@Override
public int getCount() {
    return imagesList.size();
}
public int getItemPosition(Object object) {
    return POSITION_NONE;
}
@Override
public boolean isViewFromObject(View view, Object obj) {
    return view.equals(obj);
}


@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    container.removeView((View) object);
}

public void addImages(ArrayList<Photos> img){
    for(Photos im : img){
        imagesList.add(im);
        notifyDataSetChanged();
    }

}
}

Error

 06-29 12:12:27.225 19845-19845/satlaa.mysql_test E/AndroidRuntime: FATAL EXCEPTION: main
Process: satlaa.mysql_test, PID: 19845
java.lang.IllegalStateException: The application's PagerAdapter changed the adapter's contents without calling PagerAdapter#notifyDataSetChanged! Expected adapter item count: 10, found: 30 Pager id: satlaa.mysql_test:id/viewpager Pager class: class satlaa.mysql_test.adapter.ClickableViewPager Problematic adapter: class satlaa.mysql_test.adapter.MyViewPagerAdapter
    at android.support.v4.view.ViewPager.populate(ViewPager.java:1137)
    at android.support.v4.view.ViewPager.populate(ViewPager.java:1086)
    at android.support.v4.view.ViewPager.onMeasure(ViewPager.java:1616)
    at android.view.View.measure(View.java:19857)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6083)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    at android.view.View.measure(View.java:19857)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6083)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    at android.view.View.measure(View.java:19857)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6083)
    at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1464)
    at android.widget.LinearLayout.measureVertical(LinearLayout.java:758)
    at android.widget.LinearLayout.onMeasure(LinearLayout.java:640)
    at android.view.View.measure(View.java:19857)
    at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:6083)
    at android.widget.FrameLayout.onMeasure(FrameLayout.java:185)
    at com.android.internal.policy.DecorView.onMeasure(DecorView.java:689)
    at android.view.View.measure(View.java:19857)
    at android.view.ViewRootImpl.performMeasure(ViewRootImpl.java:2275)
    at android.view.ViewRootImpl.measureHierarchy(ViewRootImpl.java:1366)
    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1619)
    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1254)
    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6337)
    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:874)
    at android.view.Choreographer.doCallbacks(Choreographer.java:686)
    at android.view.Choreographer.doFrame(Choreographer.java:621)
    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:860)
    at android.os.Handler.handleCallback(Handler.java:751)
    at android.os.Handler.dispatchMessage(Handler.java:95)
    at android.os.Looper.loop(Looper.java:154)
    at android.app.ActivityThread.main(ActivityThread.java:6119)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)

I open image in a fragment in onBindViewHolder.

((MyViewHolder) holder).itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Bundle bundle = new Bundle();
                bundle.putSerializable("url", imagesList);
                bundle.putInt("position", position);
                FragmentTransaction ft = ((Activity) mContext).getFragmentManager().beginTransaction();
                Full_Image newFragment = Full_Image.newInstance();
                newFragment.setArguments(bundle);
                newFragment.show(ft, "slideshow");

            }

FullImagefragment

  images = (ArrayList<Photos>) getArguments().getSerializable("url");=
    selectedPosition = getArguments().getInt("position");

    final int number = viewPager.getCurrentItem();
    final Photos image = images.get(number);
    final String img_title = image.getTitle();
    final String img_weight = image.getWeight();
   myViewPagerAdapter = new MyViewPagerAdapter(getActivity(), images);
    viewPager.setAdapter(myViewPagerAdapter);
    viewPager.addOnPageChangeListener(viewPagerPageChangeListener);
    setCurrentItem(selectedPosition);

Solution

  • try by removing notifyDataSetChanged(); from your

    public void addImages(ArrayList<Photos> img){
        for(Photos im : img){
           imagesList.add(im);
           notifyDataSetChanged();
        }
    }
    

    As you are doing it after adding the items in your volley response.

    Also make a swap in notifying the recycleradapter and viewPagerAdapter So instead of

     adapter.addImages(imagelist);
     myViewPagerAdapter.addImages(imagelist);
     adapter.notifyDataSetChanged();
     myViewPagerAdapter.notifyDataSetChanged();
    

    try

     myViewPagerAdapter.addImages(imagelist);
     myViewPagerAdapter.notifyDataSetChanged();
     adapter.addImages(imagelist);
     adapter.notifyDataSetChanged();