很久之前,有一位同事兼好友的技术大咖,建议我在学习新技术时,在对新知识有一个初步的认识之后,多查阅
官方文档,特别是第一手的官方文档(绝大部分是英文)。当时没有十分在意,一是自己秉承“要用才学,能解决实
际问题才学”的认知,二是自己的英文水平,要流畅地阅读官方文档,还是有问题的(学了这么多年的英语,感觉然
并卵)。现在发现:要想更深入的研究相关技术细节,阅读官方文档是不可或缺的!
研究ViewPager,少不了对PagerAdapter的研究;如下是PagerAdapter的官方解释。
Base class providing the adapter to populate pages inside of a ViewPager
. You will most likely want to use a more specific implementation of this, such as FragmentPagerAdapter
orFragmentStatePagerAdapter
.
When you implement a PagerAdapter, you must override the following methods at minimum:
instantiateItem(ViewGroup, int)
destroyItem(ViewGroup, int, Object)
getCount()
isViewFromObject(View, Object)
PagerAdapter is more general than the adapters used for AdapterViews
. Instead of providing a View recycling mechanism directly ViewPager uses callbacks to indicate the steps taken during an update. A PagerAdapter may implement a form of View recycling if desired or use a more sophisticated method of managing page Views such as Fragment transactions where each page is represented by its own Fragment.
ViewPager associates each page with a key Object instead of working with Views directly. This key is used to track and uniquely identify a given page independent of its position in the adapter. A call to the PagerAdapter method startUpdate(ViewGroup)
indicates that the contents of the ViewPager are about to change. One or more calls to instantiateItem(ViewGroup, int)
and/ordestroyItem(ViewGroup, int, Object)
will follow, and the end of an update will be signaled by a call to finishUpdate(ViewGroup)
. By the time finishUpdate
returns the views associated with the key objects returned by instantiateItem
should be added to the parent ViewGroup passed to these methods and the views associated with the keys passed to destroyItem
should be removed. The method isViewFromObject(View, Object)
identifies whether a page View is associated with a given key object.
A very simple PagerAdapter may choose to use the page Views themselves as key objects, returning them from instantiateItem(ViewGroup, int)
after creation and adding them to the parent ViewGroup. A matching destroyItem(ViewGroup, int, Object)
implementation would remove the View from the parent ViewGroup and isViewFromObject(View, Object)
could be implemented as return view == object;
.
PagerAdapter supports data set changes. Data set changes must occur on the main thread and must end with a call to notifyDataSetChanged()
similar to AdapterView adapters derived fromBaseAdapter
. A data set change may involve pages being added, removed, or changing position. The ViewPager will keep the current page active provided the adapter implements the methodgetItemPosition(Object)
.
引用自点击打开链接
为了解决不能流畅阅读英文原文的障碍,也为了提高学习效率,激发学习热情(以前看到大段的英文就头疼)。特
地从别处找来了相关API的中译文,与英文对照阅读。
提供一个适配器用于填充ViewPager页面. 你很可能想要使用一个更加具体的实现, 例如: FragmentPagerAdapter
or FragmentStatePagerAdapter
.
当你实现一个PagerAdapter时,至少需要覆盖以下几个方法:
instantiateItem(ViewGroup, int)
destroyItem(ViewGroup, int, Object)
getCount()
isViewFromObject(View, Object)
PagerAdapter比AdapterView的使用更加普通.ViewPager使用回调函数来表示一个更新的步骤,而不是使用一个视图回收机制。在需要的时候pageradapter也可以实现视图的回收或者使用一种更为巧妙的方法来管理视图,比如采用可以管理自身视图的fragment。
引用自点击打开链接
虽然翻译不是十分完美,但对照着英文原文,还是可以看出个所以然的。
上面这么长的篇幅,真正关键处在此“ViewPager associates each page with a key Object instead of
working with Views directly.This key is used to track and uniquely identify a given page independent
of its position in the adapter”这里提到了“key”——“键”,每个滑动界面都对应一个Key,而且这个Key用来
唯一追踪这个界面。“A very simple PagerAdapter may choose to use the page Views themselves as key
objects”,将当前界面本身的View作为Key。
一 destroyItem
public void destroyItem (ViewGroup container, int position, Object object)
Remove a page for the given position. The adapter is responsible for removing the view from itsContainer, although it only must ensure this is done by the time it returns fromfinishUpdate(ViewGroup)
.
Parameters
container | The containing View from which the page will be removed. |
---|---|
position | The page position to be removed. |
object | The same object that was returned by instantiateItem(View, int) . |
该方法实现的功能是移除一个给定位置的页面。适配器有责任从容器中删除这个视图。然而这是为了确保在
finishUpdate(viewGroup)返回时视图能够被移除。
而我们在《Android之ViewPager总结(一)》是如何做的呢?
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(viewList.get(position));
}
我们将给定位置的视图从container中移除了。
二 getCount
public abstract int getCount ()
Return the number of views available.
上一节的例子中我们是这样做的。
@Override
public int getCount() {
return viewList.size();
}
返回了当前要滑动视图的个数,与SDK说明一致。
三 instantiateItem
public Object instantiateItem (ViewGroup container, int position)
Create the page for the given position. The adapter is responsible for adding the view to the container given here, although it only must ensure this is done by the time it returns fromfinishUpdate(ViewGroup)
.
这个函数的实现的功能是创建指定位置的页面视图。适配器有责任增加即将创建的View视图添加到这个给定的
container中,这是为了确保在finishUpdate(viewGroup)返回时this is be done!
返回一个代表新增视图页面的Object(Key),这里没必要非要返回视图本身,也可以是这个页面的其它容
器。其实我的理解是可以代表当前页面的任意值,只要可以与你增加的View一一对应即可,比如position变量也可
以作为Key(如后面例子所示)。
“it only must ensure this is done by the time it returns fromfinishUpdate(ViewGroup).”这句话在
destroyItem()的函数说明中同样出现过,这说明在 finishUpdate(viewGroup)执行完后,有两个操作,一个是原
视图的移除(不再显示的视图),另一个是新增显示视图(即将显示的视图)。
上一节的例子中我们是这样做的。
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(viewList.get(position));
return viewList.get(position);
}
在这里,我们做了两件事。
一、将参数里给定的position位置上的视图,增加到conatiner中,供其创建并显示。
二、返回当前position的View作为此视图的Key。还记得API官方文档中下面这段话么?
A very simple PagerAdapter may choose to use the page Views themselves as key objects, returning them from instantiateItem(ViewGroup, int)
after creation and adding them to the parent ViewGroup. A matching destroyItem(ViewGroup, int, Object)
implementation would remove the View from the parent ViewGroup and isViewFromObject(View, Object)
could be implemented as return view == object;
这里就把当前的View当作Key传过出去。
四 isViewFromObject
public abstract boolean isViewFromObject (View view, Object object)
Determines whether a page View is associated with a specific key object as returned by instantiateItem(ViewGroup, int)
. This method is required for a PagerAdapter to function properly.
该方法用来判断instantiateItem(ViewGroup, int)函数所返回来的Key与一个页面视图是否是代表的同一个视图
(即它俩是否是对应的,对应的表示同一个View)如果对应的是同一个View,返回True,否则返回False。
上一节的例子中我们是这样做的。
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
return arg0 == arg1;
}
由于在instantiateItem()中,我们作为Key返回来的是当前的View,所以在这里判断时,我们直接将Key与
View看是否相等来判断是否是同一个View。