ViewPager2和ViewPager的区别?
1、ViewPager2内部实现是RecyclerView,所以ViewPager2的性能更高。
2、ViewPager2可以实现竖向滑动,ViewPager只能横向滑动。
3、ViewPager2只有一个adapter,FragmentStateAdapter继承自RecyclerView.Adapter<FragmentViewHolder>。
而ViewPager有两个adapter,FragmentStatePagerAdapter和FragmentPagerAdapter,均是继承PagerAdapter。FragmentStatePagerAdapter和FragmentPagerAdapter两者的区别是FragmentStatePagerAdapter不可以缓存,FragmentPagerAdapter可以缓存。
4、ViewPager2模式实现了懒加载,默认不进行预加载。内部是通过Lifecycle 对 Fragment 的生命周期进行管理。ViewPager会进行预加载,懒加载需要我们自己去实现
问题1:ViewPager2内部实现是RecyclerView,那为什么fling操作对ViewPager2无效?
回答:这个问题,我们就需要看一下RecyclerView中fling是在哪里执行的。
RecyclerView.onTouchEvent(MotionEvent e)
--> case MotionEvent.ACTION_UP: {
if (!((xvel != 0 || yvel != 0) && fling((int) xvel, (int) yvel)))
// mOnFlingListener!=null 才去执行。那我们去看下mOnFlingListener是在哪里设置的。
// ViewPager2设置了mOnFlingListener,所以直接return true。不再执行
--> if (mOnFlingListener != null && mOnFlingListener.onFling(velocityX, velocityY)) {
return true;
}
设置mOnFlingListener。
public void setOnFlingListener(@Nullable OnFlingListener onFlingListener) {
mOnFlingListener = onFlingListener;
}
ViewPager2.initialize()
--> mPagerSnapHelper.attachToRecyclerView(mRecyclerView);
--> setupCallbacks();@SnapHelper
--> mRecyclerView.addOnScrollListener(mScrollListener);
mRecyclerView.setOnFlingListener(this);
SnapHelper实现了mOnFlingListener
那SnapHelper是干嘛的呢?帮助RecyclerView进行滚动。之前设置gallery,进行回弹。
mOnFlingListener.onFling(velocityX, velocityY)。
--> return (Math.abs(velocityY) > minFlingVelocity || Math.abs(velocityX) > minFlingVelocity) && snapFromFling(layoutManager, velocityX, velocityY);
// 滚动到对应位置
--> int targetPosition = findTargetSnapPosition(layoutManager, velocityX, velocityY);
// 滚动到下面的第一个child
--> final boolean forwardDirection = isForwardFling(layoutManager, velocityX, velocityY);
if (forwardDirection && closestChildAfterCenter != null) {
return layoutManager.getPosition(closestChildAfterCenter);
} else if (!forwardDirection && closestChildBeforeCenter != null) {
return layoutManager.getPosition(closestChildBeforeCenter);
}
问题2:比如ViewPager2有五个页面,当从页面3进入页面4时,页面1会销毁。因为RecyclerView的cacheView的缓存数量是2。但当页面4进入页面5时,页面2为什么不会被销毁?
回答:这个就涉及到RecyclerView的预取。prefech,通过GapWorker(间隙工作)类去处理。它是在view刷新的间隙进行工作。
进入页面3,缓存页面1、2,预取页面4。进入页面5,到了最后一页了,不需要预取了,那就缓存页面2、3、4。
如果不需要预取,只需要在代码中设置,LinearLayoutMangaer.setItemPrefetchEnabled(false)
那GapWorker是在哪里初始化的呢?在RecyclerView.AttachedToWindow()中。
RecyclerView.AttachedToWindow()
--> mGapWorker = new GapWorker();
// 与RecyclerView进行绑定
--> mGapWorker.add(this);
--> mRecyclerViews.add(recyclerView);
那预取的执行在哪儿呢?在RecyclerView事件分发中。
RecyclerView.onTouchEvent(MotionEvent e)
--> case MotionEvent.ACTION_MOVE: {
if (mGapWorker != null && (dx != 0 || dy != 0)) {
mGapWorker.postFromTraversal(this, dx, dy);
// 执行GapWorker的run方法
--> recyclerView.post(this);GapWorker
--> prefetch(nextFrameNs);
--> buildTaskList();
--> flushTasksWithDeadline(deadlineNs);
}
网友评论