Android ViewPager优化

Android的ViewPager控件是我们Android App开发最常用的控件之一,本文将通过setOffscreenPageLimit增加缓存页面、setUserVisibleHint实现延迟加载、以及Adapter(FragmentPagerAdapter还是FragmentStatePagerAdapter)选择这3方面来谈谈Android ViewPager优化的一些要点。

通过setOffscreenPageLimit增加缓存页面

关于OffscreenPageLimit,Api文档里有这么一个注释

 * Set the number of pages that should be retained to either side of the
     * current page in the view hierarchy in an idle state. Pages beyond this
     * limit will be recreated from the adapter when needed.
     *
     * <p>This is offered as an optimization. If you know in advance the number
     * of pages you will need to support or have lazy-loading mechanisms in place
     * on your pages, tweaking this setting can have benefits in perceived smoothness
     * of paging animations and interaction. If you have a small number of pages (3-4)
     * that you can keep active all at once, less time will be spent in layout for
     * newly created view subtrees as the user pages back and forth.</p>
     *
     * <p>You should keep this limit low, especially if your pages have complex layouts.
     * This setting defaults to 1.</p>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

OffscreenPageLimit默认值是1,它用于限制预加载或缓存页面的个数:

  • 第一次载入时候,第2页的内容也会预装载;
  • 滑到第2页时候,第3页的内容也会预装载;
  • 滑到第3页时候,第4页的内容也会预装载,第1页被destory;

如果把OffscreenPageLimit的值改为2:

  • 第一次载入时候,第2、3页的内容也会预装载;
  • 滑到第2页时候,第4页的内容也会预装载;
  • 滑到第3页时候,第5页的内容也会预装载;
  • 滑到第4页时候,第6页的内容也会预装载,第1页被destory;

我们可以适当增加OffscreenPageLimit的值,但也不能太大,如果页面只有3-4个的话,可以考虑把全部页面都缓存起来以提高滑动的流畅性

setUserVisibleHint实现延迟加载

如果我们增大了OffscreenPageLimit了,那如果每页的Fragment都需要加装数据(如访问网络),那每个页面预加载的页面都会加载数据。如何实现延迟加载?Fragment的setUserVisibleHint方法就派上用场。以下是setUserVisibleHint的api注释:

 /**
     * Set a hint to the system about whether this fragment's UI is currently visible
     * to the user. This hint defaults to true and is persistent across fragment instance
     * state save and restore.
     *
     * <p>An app may set this to false to indicate that the fragment's UI is
     * scrolled out of visibility or is otherwise not directly visible to the user.
     * This may be used by the system to prioritize operations such as fragment lifecycle updates
     * or loader ordering behavior.</p>
     *
     * <p><strong>Note:</strong> This method may be called outside of the fragment lifecycle.
     * and thus has no ordering guarantees with regard to fragment lifecycle method calls.</p>
     *
     * @param isVisibleToUser true if this fragment's UI is currently visible to the user (default),
     *                        false if it is not.
     */
    public void setUserVisibleHint(boolean isVisibleToUser) {
    。。。
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

简单地说,就是在Fragment可视性发生变化时,setUserVisibleHint就会被回调,这样的话,我们就可以在此做些文章以实现数据的延迟加载:

boolean mIsVisible = false;
@Override
public void setUserVisibleHint(boolean isVisibleToUser) {
    super.setUserVisibleHint(isVisibleToUser);
    mIsVisible = isVisibleToUser;
    if (isVisibleToUser) {
        lazyLoad();
    }
}
 void lazyLoad() {
    if (mIsVisible && mRecyclerView != null && mAdapter != null && mAdapter.getItemCount() == 0) {
        loadData();
    }
}
void loadData(){
    //load your data here
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

这样,预加载时候因mIsVisible=false而不会真正去加装数据,只有滑动到这个页面时候才会真正去加载数据;如果滑出这个页面又滑动回来,这时候adapter如果有数据的话也不会再去加载数据

FragmentPagerAdapter还是FragmentStatePagerAdapter

FragmentStatePagerAdapter与FragmentPagerAdapter对Fragment的生命周期管理影响不同,简单地说: 
如果一个Fragment不在OffscreenPageLimit范围内,那么:

  • FragmentPagerAdapter情况下 
    • 销毁仅仅回调destoryView,而不会回调detach和onDestory
    • 再次创该Fragment时候,不会重新attach和onCreate
  • FragmentStatePagerAdapter情况下 
    • 销毁不仅回调destoryView,也会回调detach和onDestory
    • 再次创该Fragment时候,需要重新attach和onCreate

FragmentStatePagerAdapter一般用于需要动态加载而且数据量比较大的情况,它可以减少缓存数据。 
以下是Api文档对FragmentStatePagerAdapter的说明:

 * Implementation of {@link PagerAdapter} that
 * uses a {@link Fragment} to manage each page. This class also handles
 * saving and restoring of fragment's state.
 *
 * <p>This version of the pager is more useful when there are a large number
 * of pages, working more like a list view.  When pages are not visible to
 * the user, their entire fragment may be destroyed, only keeping the saved
 * state of that fragment.  This allows the pager to hold on to much less
 * memory associated with each visited page as compared to
 * {@link FragmentPagerAdapter} at the cost of potentially more overhead when
 * switching between pages.

猜你喜欢

转载自blog.csdn.net/weixin_38503885/article/details/80655052
今日推荐