美文网首页
观察者设计模式在Android开发中的应用

观察者设计模式在Android开发中的应用

作者: 老师好我是小明同学 | 来源:发表于2020-01-16 16:26 被阅读0次
    1. 模式定义

    定义对象间一种一对多的依赖关系,每当一个对象改变状态时,则所有依赖于它的对象都会
    得到通知并被自动更新。

    2. Android 源码中的观察者模式应用

    在 Android 的源码中,我们接触比较多的应该是 RecyclerView 和 ListView 了,和其搭配使用的 Adapter,有 刷新列表的 notifyDataSetChanged() 方法,那么,该方法是怎样刷新列表的呢?
    首先我们要知道,观察者模式被观察者主要涉及三个操作:注册(添加)观察者、反注册观察者、通知观察者更新。
    那 RecyclerView 是什么时候执行上述操作的呢?

    RecyclerView.java

    public void setAdapter(Adapter adapter) {
            // bail out if layout is frozen
            setLayoutFrozen(false);
            setAdapterInternal(adapter, false, true);
            requestLayout();
        }
        
    private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious,
                boolean removeAndRecycleViews) {
            if (mAdapter != null) {
                mAdapter.unregisterAdapterDataObserver(mObserver);
                mAdapter.onDetachedFromRecyclerView(this);
            }
            if (!compatibleWithPrevious || removeAndRecycleViews) {
                removeAndRecycleViews();
            }
            mAdapterHelper.reset();
            final Adapter oldAdapter = mAdapter;
            mAdapter = adapter;
            if (adapter != null) {
                // 1. 看到此处
                adapter.registerAdapterDataObserver(mObserver);
                adapter.onAttachedToRecyclerView(this);
            }
            if (mLayout != null) {
                mLayout.onAdapterChanged(oldAdapter, mAdapter);
            }
            mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
            mState.mStructureChanged = true;
            setDataSetChangedAfterLayout();
        }
    

    在上面的代码 adapter.registerAdapterDataObserver(mObserver); 中,可以看到这就是注册观察者了,此方法属于 RecyclerView 内部类 Adapter

    public abstract static class Adapter<VH extends ViewHolder> {
        public void registerAdapterDataObserver(AdapterDataObserver observer) {
                mObservable.registerObserver(observer);
            }
            
        public void unregisterAdapterDataObserver(AdapterDataObserver observer) {
                mObservable.unregisterObserver(observer);
            }
            
        public final void notifyDataSetChanged() {
                mObservable.notifyChanged();
            }
    }
    

    当我们更新 RecyclerView 数据源的时候,执行了 adapter.notifyDataSetChanged(); 方法,那么此方法又做了什么工作呢?

    RecyclerView 内部类 Adapter

    public final void notifyDataSetChanged() {
                mObservable.notifyChanged();
            }
    

    RecyclerView 内部类 AdapterDataObservable

    static class AdapterDataObservable extends Observable<AdapterDataObserver> {
           
            public void notifyChanged() {
                // since onChanged() is implemented by the app, it could do anything, including
                // removing itself from {@link mObservers} - and that could cause problems if
                // an iterator is used on the ArrayList {@link mObservers}.
                // to avoid such problems, just march thru the list in the reverse order.
                for (int i = mObservers.size() - 1; i >= 0; i--) {
                    mObservers.get(i).onChanged();
                }
            }
            
    }
    

    RecyclerView 内部类 AdapterDataObserver

    public abstract static class AdapterDataObserver {
            public void onChanged() {
                // Do nothing
            }
            
    }
    

    还记得上面我们注册的方法入的参数吗?就是 一个 AdapterDataObserver 对象

    adapter.registerAdapterDataObserver(mObserver);
    

    那么,这个 mObserver 是何物?

    private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
    

    RecyclerView 内部类 RecyclerViewDataObserver

    private class RecyclerViewDataObserver extends AdapterDataObserver {
            RecyclerViewDataObserver() {
            }
    
            @Override
            public void onChanged() {
                assertNotInLayoutOrScroll(null);
                mState.mStructureChanged = true;
    
                setDataSetChangedAfterLayout();
                if (!mAdapterHelper.hasPendingUpdates()) {
                    requestLayout();
                }
            }
            
    }
    

    在此处,RecyclerView 会 requestLayout 等操作把列表给更新过来。

    以上就是 RecyclerView 刷新列表的源码分析了,使用了观察者设计模式,对此,我们也可以使用该模式去处理一些有观察和被观察关系的场景。

    3. 以公众号推送为例介绍观察者设计模式的精简用法

    观察者:观察者需要被 push

    观察者具有的操作接口

    public interface IWXUser {
        public void push(String article);
    }
    

    观察者

    public class WXUser implements IWXUser {
    
        private String name;
    
        public WXUser(String name) {
            this.name = name;
        }
    
        @Override
        public void push(String article) {
            System.out.println(name + " 收到了一篇文章:" + article);
        }
    }
    

    被观察者:各种公众号

    public class WXPublicObservable {
        // 所有订阅的用户(公众号用户)
        public List<IWXUser> mWXUsers;
    
        public WXPublicObservable(){
            mWXUsers = new ArrayList<>();
        }
    
        /**
         * 订阅
         */
        public void register(IWXUser wxUser){
            mWXUsers.add(wxUser);
        }
    
        /**
         * 取消订阅
         * @param wxUser
         */
        public void unregister(IWXUser wxUser){
            mWXUsers.remove(wxUser);
        }
    
        /**
         * 更新文章
         * @param article
         */
        public void update(String article){
            // 推送文章更新
            for (IWXUser wxUser : mWXUsers) {
                wxUser.push(article);
            }
        }
    }
    

    具体的被观察者

    public class WXxxxObservable extends WXPublicObservable {
        private String article;
    
        public String getArticle() {
            return article;
        }
    
        public void setArticle(String article) {
            this.article = article;
            // 通知更新,推送给微信用户
            update(article);
        }
    }
    
    3. 使用介绍
    public class Client {
        public static void main(String[] args){
            // 微信公众号 - 具体的被观察者 - xxx
            WXxxxObservable WXxxxObservable = new WXxxxObservable();
    
            // 微信公众号 - 具体的观察者 vegen 和 小明同学
            WXUser vegen = new WXUser("vegen");
            WXUser xiaoming = new WXUser("小明同学");
    
            // 微信公众号 - 用户订阅公众号
            WXxxxObservable.register(vegen);
            WXxxxObservable.register(xiaoming);
    
            // 微信公众号 - 推送文章
            WXxxxObservable.setArticle("我是文章巴拉巴拉1");
    
            // 微信公众号 - 用户取消订阅公众号
            WXxxxObservable.unregister(vegen);
    
            // 微信公众号 - 推送文章
            WXxxxObservable.setArticle("我是文章巴拉巴拉2");
        }
    
    }
    

    vegen 和 小明同学 都能收到 文章巴拉巴拉1 的提示,vegen 后面取消了订阅,就只有 小明同学收到了 文章巴拉巴拉2 的提示。

    相关文章

      网友评论

          本文标题:观察者设计模式在Android开发中的应用

          本文链接:https://www.haomeiwen.com/subject/bhofzctx.html