本文主要解决应用ViewPager和PagerAdapter时,调用ViewPager中的getAdapter()方法,获取Adapter对象之后调用notifyDataSetChanged()方法如何达到更新数据的目的。先不考虑FragmentStatePagerAdapter和FragmentPagerAdapter这两个基于PagerAdpter的衍生类
- 首先一张图来看下ViewPager和PagerAdapter里面会涉及到的东西
主要类的简单介绍
- ViewPager
这是一个用于翻页展示的类,里面包含了用于展示的相关信息
- ViewPager
static class ItemInfo {
Object object;//每次用于展示的对象
int position;//每个Item的在ViewPager中的位置
boolean scrolling;//是否在滚动
float widthFactor;//表示加载的页面占ViewPager所占的比例[0~1](默认返回1)
float offset;//偏移量
}
private class PagerObserver extends DataSetObserver {
@Override
public void onChanged() {
dataSetChanged();
}
@Override
public void onInvalidated() {
dataSetChanged();
}
}
这是一个对数据集(DataSet)进行观察的类,当数据集改变时,会调用他的onChanged()或者onInvalidated()方法。这个对象需要在PagerAdapter()中的被观察者(DataSetObservable)中进行注册
对于setAdapter()方法:
public void setAdapter(PagerAdapter adapter) {
if (mAdapter != null) {
mAdapter.unregisterDataSetObserver(mObserver);
mAdapter.startUpdate(this);//注销观察者
for (int i = 0; i < mItems.size(); i++) {
final ItemInfo ii = mItems.get(i);
mAdapter.destroyItem(this, ii.position, ii.object);
//使得在ViewPager中调用PagerAdapter里面的方法成为了可能
}
mAdapter.finishUpdate(this);
mItems.clear();
removeNonDecorViews();
mCurItem = 0;
scrollTo(0, 0);
}
//省略....
if (mAdapter != null) {
if (mObserver == null) {
mObserver = new PagerObserver();
}
mAdapter.registerDataSetObserver(mObserver);//注册观察者
//以下省略...
}
//以下省略...
}
setAdapter()方法建立了ViewPager和PagerAdapter的联系,通过注册观察者,让ViewPager能够接收到数据变化时,重新加载数据的请求
- PagerAdapter类
主要作用是为了给ViewPager提供需要展示的内容,这是一个内容生成器。需要说明的是这是一个抽象类,需要在继承时实现里面的
- instantiateItem():在这里面初始化Item的内容
- destroyItem() : 销毁Item
- getCount() : 返回Item的数目
- isViewFromObject()。标识一个视图是否和给定的Key对象相关[1]
3 . 当数据变化时的流程
首先在activity中会调用 ViewPager.getAdapter().notifyDataSetChanged()方法,通知数据发生改变
public void notifyDataSetChanged() {
mObservable.notifyChanged();
//然后去调用DataSetObservable类中的方法
}
DataSetObservable类中:
public void notifyChanged() {
synchronized(mObservers) {
for (int i = mObservers.size() - 1; i >= 0; i--) {
mObservers.get(i).onChanged();
//通知所有观察者数据发生变化,其中包括已经在setAdapter()时注册的PagerObserver
}
}
}
在ViewPager内部类PagerObserver中接收到通知(这是观察者模式的应用)并调用其中的onChanged()方法里面的dataSetChanged()方法,我们看到这个方法的内容:
void dataSetChanged() {
// This method only gets called if our observer is attached, so mAdapter is non-null.
for (int i = 0; i < mItems.size(); i++) {
final ItemInfo ii = mItems.get(i);
final int newPos = mAdapter.getItemPosition(ii.object);
if (newPos == PagerAdapter.POSITION_UNCHANGED) {
continue;
}
if (newPos == PagerAdapter.POSITION_NONE) {
mItems.remove(i);
i--;
if (!isUpdating) {
mAdapter.startUpdate(this);
isUpdating = true;
}
mAdapter.destroyItem(this, ii.position, ii.object);
needPopulate = true;
//这里是对PagerAdapter.getItemPosition()方法的返回值进行判断:
//POSITION_NONE时进行数据更新,
//POSITION_UNCHANGED时,标识符 needPopulate=false 不更新数据
.
.
.
if (needPopulate) {
.
.
.
setCurrentItemInternal(newCurrItem, false, true);
//这里会去调用populate()方法(这个方法的主要作用就是加载和渲染页面)
//重新做了加载数据的操作
requestLayout();
}
}
到此数据更新完成。
4 .参考:
a.http://www.cnblogs.com/dancefire/archive/2013/01/02/why-notifydatasetchanged-does-not-work.html
b.http://blog.youkuaiyun.com/u011494050/article/details/45366763
c.http://www.jianshu.com/p/85afaf9e8f6e
d.http://blog.youkuaiyun.com/u011494050/article/details/45366763
[1].http://blog.youkuaiyun.com/dmk877/article/details/50060745