Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PagerAdapter.notifyDataSetChanged does not refresh fragments

My Activity contains a ViewPager and it's custom Adapter which extends FragmentStatePagerAdapter. ViewPager contains 3 fragments

Code to remove Fragments from the ViewPager

MainActivity

public void deleteElement(){
    final int currentItem = mViewPager.getCurrentItem();
    mPagerAdapter.removeItem(currentItem);
    mPagerAdapter.notifyDataSetChanged();
}

CustomPagerAdapter

private ArrayList<Item> data;
public void removeItem(int index){
        data.remove(index);
}

when removing the middle Fragment (index 1):

  • from data i'm removing the correct item.
  • Problem is that i (i guess) Fragment 3 is removed after notifyDataSetChanged and the current Fragment is still the fragment that the user saw and the data that is being loaded is from the SavedInstance bundle

So the end result that the user still see the same Fragment that he tried to remove which is kinda suck for him.

Ideas?

***** EDIT ******

seems like ViewPager2 Features might solve this issue and many other issues as well

like image 974
royB Avatar asked Jan 23 '15 18:01

royB


People also ask

How do I refresh FragmentStateAdapter?

You can use startActivityForResult(or broadcast/receiver) to get the result from the activity. Then use adapter. notifyDataSetChanged to refresh the fragment.

How do I refresh ViewPager2?

As we already know that ViewPager2 is built on RecyclerView that's why it's easy to update only one item by calling the method notifyItemChanged(index). If we want to update all items then we can also do this by simply calling the notifyDatasetChanged() method. That's it for now.

What is the difference between PagerAdapter and Fragmentpageradapter?

The difference is that you can use Fragments inside a FragmentPageAdapter . If you want to have fragments that are going to be used in other parts of your code this is your Adapter. Otherwise if you only want to have code that isn't going to be reused, you can use PagerAdapter .

What is difference between ViewPager and ViewPager2?

ViewPager2 is an improved version of the ViewPager library that offers enhanced functionality and addresses common difficulties with using ViewPager . If your app already uses ViewPager , read this page to learn more about migrating to ViewPager2 .


2 Answers

Try adding this:

private class MyPagerAdapter extends FragmentStatePagerAdapter {

//... your existing code

    @Override
    public int getItemPosition(Object object){
        return PagerAdapter.POSITION_NONE;
    }

}
like image 56
kelvincer Avatar answered Sep 23 '22 01:09

kelvincer


You have no choice but to implement PagerAdapter#getItemPosition. Looking at the source that's exactly how ViewPager determines how to update its position, add new fragments or drop dead ones after notifyDataSetChanged. It shouldn't be too hard, you just need to access the state of the passed fragment, and you also need to access the master state in your activity which holds your ordering.

It's also required you implement getItemId to return a consistent ID for each fragment, because they can be reordered.

This is how I handled it in a ViewPager of photos.

    private inner class PhotoPagerAdapter(fm: FragmentManager) : FragmentPagerAdapter(fm) {
    override fun getItem(position: Int): PhotoViewFragment {
        // getItem is called to instantiate the fragment for the given page.
        return PhotoViewFragment.newInstance(position, [email protected][position])
    }

    override fun getItemId(position: Int): Long {
        return [email protected][position].ID!!.hashCode().toLong()
    }

    override fun getItemPosition(`object`: Any): Int {
        val frag = `object` as PhotoViewFragment
        val idx = [email protected] { ph -> ph.ID == frag.dataBinding.photo.ID }
        return if (idx >= 0) idx else PagerAdapter.POSITION_NONE
    }

    override fun getCount(): Int {
        return [email protected]
    }
}
like image 30
androidguy Avatar answered Sep 20 '22 01:09

androidguy