为了账号安全,请及时绑定邮箱和手机立即绑定

FragmentPagerAdapter和FragmentStatePagerAdapter源码中的三宝【下】

标签:
Android
观察者模式

首先声明:虽然在ViewPager(充当观察者)和PagerAdapter(充当被观察者)中出现了观察者模式的代码,但是ViewPager中并未注册观察者。不过这里的案例非常经典,不由得分析下作为记录。同样的,ListView(充当观察者)和BaseAdapter(充当被观察者)则使用了这个模式并在ListView中注册了观察者,有兴趣的可以查看相关源码。

前面讲了一个伪观察者模式,继续....

仍然是上次的代码,notifyDataSetChanged最后一行调用了
mObservable.notifyChanged() 这才是正宗的观察者模式。

public abstract class PagerAdapter {
    // 被观察者
    private final DataSetObservable mObservable = new DataSetObservable();

    public void notifyDataSetChanged() {
        synchronized (this) {
            // 冒充者
            if (mViewPagerObserver != null) {
                mViewPagerObserver.onChanged();
            }
        }
        // 正宗
        mObservable.notifyChanged();
    }

    public void registerDataSetObserver(DataSetObserver observer) {
        mObservable.registerObserver(observer);
    }

    public void unregisterDataSetObserver(DataSetObserver observer) {
        mObservable.unregisterObserver(observer);
    }
}

如何在PagerAdapter 中给 被观察者DataSetObservable 注册一个观察者?

注意:这段代码仅做参考,Android并未真正注册。

PagerAdapter pagerAdapter = new .. ;
pagerAdapter.registerDataSetObserver(new DataSetObserver() {
    @Override
    public void onChanged() {
        super.onChanged();
        // .... 实现,这里copy伪娘那里的onChange()方法.
    }

    @Override
    public void onInvalidated() {
        super.onInvalidated();
        // .... 实现
    }
});

下面我们就来一起看看Android的被观察者和观察者是怎么写的,可以借鉴参考下:

被观察者
DataSetObservable

public class DataSetObservable extends Observable<DataSetObserver> {
    public void notifyChanged() {
        synchronized(mObservers) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }

    public void notifyInvalidated() {
        synchronized (mObservers) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onInvalidated();
            }
        }
    }
}

Observable

package android.database;

import java.util.ArrayList;

public abstract class Observable<T> {

    protected final ArrayList<T> mObservers = new ArrayList<T>();

    public void registerObserver(T observer) {
        if (observer == null) {
            throw new IllegalArgumentException("The observer is null.");
        }
        synchronized(mObservers) {
            if (mObservers.contains(observer)) {
                throw new IllegalStateException("Observer " + observer + " is already registered.");
            }
            mObservers.add(observer);
        }
    }

    public void unregisterObserver(T observer) {
        if (observer == null) {
            throw new IllegalArgumentException("The observer is null.");
        }
        synchronized(mObservers) {
            int index = mObservers.indexOf(observer);
            if (index == -1) {
                throw new IllegalStateException("Observer " + observer + " was not registered.");
            }
            mObservers.remove(index);
        }
    }

    public void unregisterAll() {
        synchronized(mObservers) {
            mObservers.clear();
        }
    }
}

观察者

package android.database;

public abstract class DataSetObserver {

    public void onChanged() {
        // Do nothing
    }

    public void onInvalidated() {
        // Do nothing
    }
}

这就是Android经典的观察者模式.

源码扩展

ListView和ViewPager在适配器模式和观察者模式存在诸多相似,举一反三让我们的理解更加透彻。

ListView在setAdapter() 中注册的观察者.

public void setAdapter(ListAdapter adapter) {
    if (mAdapter != null && mDataSetObserver != null) {
        mAdapter.unregisterDataSetObserver(mDataSetObserver);
    }

    resetList();
    mRecycler.clear();

    if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
        mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, adapter);
    } else {
        mAdapter = adapter;
    }

    mOldSelectedPosition = INVALID_POSITION;
    mOldSelectedRowId = INVALID_ROW_ID;

    super.setAdapter(adapter);

    if (mAdapter != null) {
        // 注册观察者
        mDataSetObserver = new AdapterDataSetObserver();
        mAdapter.registerDataSetObserver(mDataSetObserver);
    }

    requestLayout();
}
点击查看更多内容
1人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消