从功能说起
ViewPager 是什么?是一种布局结构,并且还是一个类。
当为UI添加ViewPager后,用户可左右滑动屏幕,切换查看不同列表项的明细页面。
需要做哪些工作
为了添加ViewPager具体功能实现,我们要做以下工作:
- 创建 Activity 实例,这个 Activity 里来存放 ViewPager 视图
- 定义包含 ViewPager 的视图层级结构
- 在 Activity 类中关联使用 ViewPager 以及 Adapter
通过这个结构图我们可以看出,通过点击事件 CrimeListFragment 来启动 CrimePagerActivity ,并且CrimePagerActivity 中包含了一个 ViewPager
PagerAdapter
ViewPager 需要 PagerAdapter 的支持, Google提供了PagerAdapter的子类FragmentStatePaferAdapter ,它能协助处理许多事情。如下面代码所示
1 | FragmentManager fragmentManager = getSupportFragmentManager(); |
FragmentStatePagerAdapter 提供了两个有用的方法,我们必须进行方法覆盖
getItem(int)
获取并显示crime 数组中指定位置的Crime时,他会返回配置过得CrimeFragment来显示指定的CrimegetCount()
返回数组列表中包含的列表项数目
注意,创建FragmentStatePagerAdapter实例需要FragmentManager
FragmentStatePagerAdapter 与FragmentPagerAdapter
- 区别:前者在滑动过后,调用 remove() 方法将 fragment 移除。而后者不会移除,只是销毁了视图,fragment 实例还保存在 FragmentManager 中。
- 应用:由此看来,后者会占用大量内存来换取加载速度,所以前者在大容量 fragment 的情况下,例如每个 fragment 都是一个高清图片且数量上百上千,那么适合用前者。如果数量少或者比较重视响应or加载速度,建议用后者,加载速度快。
工作原理
为何不用RecyclerView
上一篇博客提到,RecyclerView也可以提供横着翻的实例,为什么不用它呢?
由于无法使用现有的fragment, 因此在 CriminalIntent 应用中使用 RecyclerView 需处理大量内部实现工作。Adapter 需要我们及时地提供View。然而,决定 fragment 视图何时创建的是 FragmentManager 。因此, 当RecyclerView 要求Adapter提供fragment视图时,我们无法立即创建fragment并提供视图。
所以,核心的区别在于Adapter和PagerAdapter的区别。
PagerAdapter
1 | public Object instantiateItem(ViewGroup container, int position) |
PagerAdapter.instantiateItem告诉pager adapter创建指定位置的列表项视图, 然后将其添加给ViewGroup视图容器, 而destroyItem告诉pager adapter销毁已建视图。
视图创建完成之后,ViewPager会在某个时间点看到它。未确定该视图所属对象, ViewPager会调用isViewFromObject,这里的Obj是instantiateItem返回的对象。因此假设ViewPager调用instantiateItem(ViewGroup, 5)返回A对象,那么只要传入的View参数是第5个对象的视图,isViewFromObject(View, A)方法就应该返回true,否则返回false。
当然,以上这些其实都封装在了FragemntPagerAdapter和FragemntStatePagerAdapter 中,当我们使用的时候并不需要具体实现。
(2019-8-20更新)
注意:这里面 FragmentStatePagerAdapter 并不是绝对的退出视野就调用 destoryItem ,当我在Android 模拟器里观察内部调用机制时,我们发现pagerAdapter会保留三个视图,当前视图,上一个视图和下一个视图,猜测是方便加载。举个例子,当我们从第二个视图跳转到第一个视图时,并不会调用 creatItem()
,因为 3 -> 2 时已经预先创建了 1。