For the More Curious: How ViewPager Really Works

The ViewPager and PagerAdapter classes handle many things for you behind the scenes. This section will supply more details about what is going on back there.

A caveat before we get into this discussion: You do not need to understand the nitty-gritty details in most cases.

But, if you need to implement the PagerAdapter interface yourself, you will need to know how the ViewPager-PagerAdapter relationship differs from an ordinary RecyclerView-Adapter relationship.

When would you need to implement the PagerAdapter interface yourself? When you want ViewPager to host something other than Fragments. If you want to host normal View objects in a ViewPager, like a few images, you implement the raw PagerAdapter interface.

So why is ViewPager not a RecyclerView?

Using a RecyclerView in this case would be a lot of work because you could not use your existing Fragment. An Adapter expects you to provide a View instantly. However, your FragmentManager determines when your fragment’s view is created, not you. So when RecyclerView comes knocking at your Adapter’s door for your fragment’s view, you will not be able to create the fragment and provide its view immediately.

This is the reason ViewPager exists. Instead of an Adapter, it uses PagerAdapter. PagerAdapter is more complicated than Adapter because it does more of the work of managing views than Adapter does. Here are the basics.

Instead of an onBindViewHolder(…) method that returns a view holder and its corresponding view, PagerAdapter has the following methods:

    public Object instantiateItem(ViewGroup container, int position)
    public void destroyItem(ViewGroup container, int position, Object object)
    public abstract boolean isViewFromObject(View view, Object object)

PagerAdapter.instantiateItem(ViewGroup, int) tells the pager adapter to create an item view for a given position and add it to a container ViewGroup, and destroyItem(ViewGroup, int, Object) tells it to destroy that item. Note that instantiateItem(ViewGroup, int) does not say to create the view right now. The PagerAdapter could create the view at any time after that.

Once the view has been created, ViewPager will notice it at some point. To figure out which item’s view it is, it calls isViewFromObject(View, Object). The Object parameter is an object received from a call to instantiateItem(ViewGroup, int). So if ViewPager calls instantiateItem(ViewGroup, 5) and receives object A, isViewFromObject(View, A) should return true if the View passed in is for item 5, and false otherwise.

This is a complicated process for the ViewPager, but it is less complicated for the PagerAdapter, which only needs to be able to create views, destroy views, and identify which object a view comes from. This loose requirement gives a PagerAdapter implementation enough wiggle room to create and add a new fragment inside instantiateItem(ViewGroup, int) and return the fragment as the Object to keep track of. Then isViewFromObject(View, Object) looks like this:

@Override
public boolean isViewFromObject(View view, Object object) {
    return ((Fragment)object).getView() == view;
}

Implementing all those PagerAdapter overrides would be a pain to do every time you needed to use ViewPager. Thank goodness for FragmentPagerAdapter and FragmentStatePagerAdapter.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.217.60.35