ViewPager2 major update, support offscreenPageLimit

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/xiangzhihong8/article/details/91496705

Foreword

ViewPager2 recently released version 1.0.0-alpha04, offscreenPageLimit new feature, which is not friendly on ViewPager, the following is the official description for the ViewPager2:
Here Insert Picture Description
As we all know, ViewPager there are two problems: 不能关闭预加载和更新Adapter不生效so in the beginning why I say offscreenPageLimit ViewPager on very unfriendly; because offscreenPageLimit can not be set to 0 (set to 0 is the preloading imaginary) nature.
Here Insert Picture Description
The above is a schematic view in the case ViewPager loaded by default, when switching to the current page, the default layout will be preloaded into the left and right sides of ViewPager, although not visible on both sides of View, we call this a condition called pre-loading; due ViewPager of offscreenPageLimit set a limit, preloaded page is inevitable. ViewPager source as follows:

private static final int DEFAULT_OFFSCREEN_PAGES = 1;

public void setOffscreenPageLimit(int limit) {
    if (limit < DEFAULT_OFFSCREEN_PAGES) {//不允许小于1
        Log.w(TAG, "Requested offscreen page limit " + limit + " too small; defaulting to "
                + DEFAULT_OFFSCREEN_PAGES);
        limit = DEFAULT_OFFSCREEN_PAGES;
    }
    if (limit != mOffscreenPageLimit) {
        mOffscreenPageLimit = limit;
        populate();
    }
}

However, ViewPager logic mandatory pre-loaded with the remains in the Fragment ViewPager use. In order not to pre-loaded, you can use the Fragment lazy loading. Let me talk about ViewPager with PagerAdapter lazy loading method to achieve, commonly used methods are the following:

  • instantiateItem (ViewGroup container, int position): initialize ItemView, need to add ItemView is returned;
  • destroyItem (iewGroup container, int position, Object object): Destruction ItemView, removal of specified ItemView;
  • isViewFromObject (View view, Object object): View Object and correspond;
  • setPrimaryItem (ViewGroup container, int position, Object object): Item current master page;
  • getCount (): Get Number Item

Let me setPrimaryItem (ViewGroup container, int position, Object object), which represents the current page being displayed mainly Item, what is the main Item? If the pre-loaded ItemView has been assigned to the screen, the current PrimaryItem still will not change unless new ItemView fully included screen and slide has stopped before judgment, involving code is as follows:
Here Insert Picture Description
As the ViewPager inevitable layout preload, resulting in PagerAdapter must call in advance instantiateItem (ViewGroup container, int position) method, instantiateItem () is the only way to create ItemView entrance, so PagerAdapter implementation class FragmentPagerAdapter and FragmentStatePagerAdapter must seize this method to create a Fragment object. For example:
Here Insert Picture Description
It should be noted, FragmentPagerAdapter FragmentStatePagerAdapter and fall in instantiateItem () and are created for add or attach operation, and not to operate Fragment setPrimaryItem () method. Thus, the preload results in a call onCreate invisible Fragment of fall, onCreateView, onResume the like, only the user identified by Fragment.setUserVisibleHint () method.
Most are lazy loading of Fragment tricks, combining life-cycle approach and setUserVisibleHint status, control data, lazy loading, and can only enter the layout in advance;

ViewPager2

Before using ViewPager2, need to be introduced ViewPager2 library, just add the following to rely on build.gradle introduction:

implementation 'androidx.viewpager2:viewpager2:1.0.0-alpha04'

Then, in the layout introduced:

<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/view_pager"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

ViewPager2 can be used with Adapter, it can also be used with Fragment.

ViewPager2 viewPager = findViewById(R.id.view_pager2);
viewPager.setAdapter(new RecyclerView.Adapter<ViewHolder>() {
        @Override
        public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
            View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_card_layout, parent, false);
            ViewHolder viewHolder = new ViewHolder(itemView);
            return viewHolder;
        }
        @Override
        public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
            holder.labelCenter.setText(String.valueOf(position));
        }
        @Override
        public int getItemCount() {
            return SIZE;
        }
    }));

static class ViewHolder extends RecyclerView.ViewHolder{
    private final TextView labelCenter;
    public ViewHolder(@NonNull View itemView) {
        super(itemView);
        labelCenter = itemView.findViewById(R.id.label_center);
    }
}

Of course, ViewPager2 and can also be used in conjunction Fragment.

viewPager.setAdapter(new FragmentStateAdapter(this) {
        @NonNull
        @Override
        public Fragment getItem(int position) {
            return new VSFragment();
        }

        @Override
        public int getItemCount() {
            return SIZE;
        }
    });

ViewPager2 and ViewPager similar way in the use, mainly in some of the following API:

  • of the setAdapter () Set adapter
  • the setOrientation () sets the layout direction
  • setCurrentItem () to set the current index Item
  • beginFakeDrag () start the simulation drag
  • fakeDragBy () drag the analog
  • endFakeDrag () simulate the drag end
  • setUserInputEnabled () settings allow the user to enter / touch
  • setOffscreenPageLimit () Set the number of pages to load external screen
  • registerOnPageChangeCallback () callback to change the registration page
  • setPageTransformer () conversion settings page sliding effect

Offscreen load

In version 1.0.0-alpha04, ViewPager2 loading function provides off-screen, meaning the pre-loading function and ViewPager stored seems to be the same.

public static final int OFFSCREEN_PAGE_LIMIT_DEFAULT = 0;

public void setOffscreenPageLimit(int limit) {
    if (limit < 1 && limit != OFFSCREEN_PAGE_LIMIT_DEFAULT) {
        throw new IllegalArgumentException(
                "Offscreen page limit must be OFFSCREEN_PAGE_LIMIT_DEFAULT or a number > 0");
    }
    mOffscreenPageLimit = limit;
    // Trigger layout so prefetch happens through getExtraLayoutSize()
    mRecyclerView.requestLayout();
}

In order to facilitate the analysis of the difference between ViewPager2 and ViewPager, we look at the layout of the comparison:

Contrast layout

To compare the effect of both loading layout, while demonstrating LinearLayout I prepared ViewPager and ViewPager2, set the same layout and Item data sources, analyzing the layout and configuration of the tool with both Android layout gripping effect is as follows:
Here Insert Picture Description
From the analysis results, , a ViewPager sides are pre-default layout of a layout, ViewPager2 without pre-layout by default, is determined by the main offscreenPageLimit their default parameters, defaults to 1 and does not allow a ViewPager less than 1, ViewPager2 defaults to 0.
Here Insert Picture Description
Analysis of operating results, when the same offscreenPageLimit provided, around both of which the pre-layout (vertical) both a ItemView is offscreenPageLimit;
from the results, comparison, operation results and ViewPager2 the offscreenPageLimit ViewPager same, but ViewPager2 0 may be set to the minimum offscreenPageLimit ;

Preloading and caching

ViewPager2 preload preload RecyclerView i.e., the code in the GapWorker in RecyclerView. ViewPager2 preloaded on by default, in form of control, or drag Fling, a data may be preloaded; Here is a schematic diagram preloaded:
Here Insert Picture Description
To close the preload, you can use the following code:

((RecyclerView)viewPager.getChildAt(0)).getLayoutManager().setItemPrefetchEnabled(false);

Pre-loaded in the switch LayoutManager, only needs to obtain and call LayoutManager setItemPrefetchEnabled () to control the switch;
ViewPager2 default cache ItemView is 2, and the number of buffers can be customized in Item RecyclerView the latest, as follows:

public void setItemViewCacheSize(int size) {
    mRecycler.setViewCacheSize(size);
}

Preloading and caching is no essential difference in the View level, are already prepared layout, but not loaded into the parent view; pre-loaded and off-loaded in the View screen is fundamentally different level, off-screen View loaded has been added to the parent on;

Fragment of support for preloading

Currently, ViewPager2 support for Fragment can only be achieved using FragmentStateAdapter, it is also very simple to use, for example:
Here Insert Picture Description
by default, ViewPager2 is on pre-loaded shut down off-screen loaded, in this case, switch the page to what the lifecycle Fragment impact? The following are two graphs from the network:
Here Insert Picture Description
One problem: preloading impact on Fragment of : a proven, pre-loading is turned on, there is no impact on the Fragment of the life cycle, and the result is the same as the default chart;
Second problem: open offscreen loading effect on the Fragment : when setting offscreenPageLimit = 1:
Here Insert Picture Description
As can be seen from the print log, offscreenPageLimit = time 1, ViewPager2 on page 1 loads two data, and the next page will be loaded in advance View in; after every a slide, loads the next array, until page 5, it will remove the page Fragment 1; page 6 page will remove Fragment 2.

summary

For this update, ViewPager2 mainly has the following features:

  1. Currently ViewPager2 support can only be used for Fragment FragmentStateAdapter, FragmentStateAdapter in the face of pre-loaded, it will only create Fragment object will not Fragment really added to the layout, it comes with lazy loading effect;
  2. FragmentStateAdapter will not remain Fragment example, recycled ItemView also removes Fragment, so you have to be ready to recover data after Fragment reconstruction;
  3. FragmentStateAdapter in the face of offscreenPageLimit> 0, there is no difference between treatment and visible off-screen Fragment Fragment, so I can not judge setUserVisibleHint display or not by;

Through this ViewPager2 update, the official looks to replace ViewPager force, whether it is efficient reuse or lazy load comes about, or update effective Adapter, to be more powerful than ViewPager.

Guess you like

Origin blog.csdn.net/xiangzhihong8/article/details/91496705