ViewPager 在 Android 开发中是最常用的控件之一,最近刚好有时间,于是看了一下它的源码,顺便做个笔记记录一下。
看源码,我们一般会带着问题去看,这样效果可能会更好一些。看 ViewPager 源码,我主要是想弄清一下的几个问题。
–
1.疑问
- ViewPager 是直接继承 ViewGroup 的,继承 ViewGroup 的自定义控件要在 onMeasure() 和 onLayout() 方法中对 childView 进行处理的,ViewPager 是如何做的?
- ViewPager 是如何计算滑动的距离,并滑动到相应的位置?
- ViewPager 是如何处理点击事件的拦截,并处理相应的事件冲突的?
- ViewPager#setOffscreenPageLimit(int limit) 是如何实现界面缓存数量的限制的?
-
2. 分析
入口 setAdapter –> onMeasure / populate –> onLayout
1. 对 setAdapter(…) 的分析
ViewPager#setAdapter(PagerAdapter adapter) 是对 ViewPager 分析的入口,这个方法里面的代码比较简单,我们只需要知道如果是第一次布局,它会调用 requestLayout() 对 ViewPager 重新进行布局。
2. 对 onMeasure(…) 的分析
先看分析代码
1 |
|
具体的分析在上面的源码已经加了注释,主要是:
. 存储 ViewPager 自身测量的宽高.
. 调用 populate() 方法,稍后分析.
. 对 childView 进行测量,这是继承 ViewGroup 自定义 View 都要做的.
3. 对 papulate(…) 分析
注释的源码
1 | void populate(int newCurrentItem) { |
populate(…) 主要做了:
. 设置了缓存界面数量的限制.
. 生成 ItemInfo, ItemInfo 是对 childView 的包装,方便 ViewPager 进行管理.
. 对左边和右边的 childView 进行处理.
. 对用 calculatePageOffsets,计算界面的偏移量,通过计算 ItemInfo.offset 的值,得出偏移量.
4. 对 onLayout(…) 分析
onLaout(…) 中是按普通 ViewGroup 对每个 childView 进行 layout 即可
5. 其他重要的方法
scrollToItem(…) 滑动
使用 Scroller 来完成滑动的onInterceptTouchEvent() 处理事件拦截
只有在拖动的情况下才会进行拦截.预加载的问题 ViewPager#setOffscreenPageLimit
默认是 1.
在 populate(…) 方法中计算 starPos 和 endPos 用到了
1 | final int pageLimit = mOffscreenPageLimit; |
形成了
1 | [startPos, currenPos, endPos] |
-
3. 其他收获
. 下面的代码写法可以借鉴,先从 List 中取,如果取到的结果为空,则生成一个并存放到 List 中,并返回。这样下次取的时候就可以用了这样避免了一次生成多个对象,减少了申请内存空间的分配,减少内存抖动。
1 | int curIndex = -1; |
- 另外 Arrays.sor() 排序使用到了 DulPivotQuickSort.sort() 快速排序算法。有时间要去研究一下。