美文网首页
观察者设计模式-RecyclerView中的观察者

观察者设计模式-RecyclerView中的观察者

作者: _风听雨声 | 来源:发表于2020-04-11 23:24 被阅读0次

观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其相关依赖对象皆得到通知并被自动更新。观察者模式又叫做发布-订阅(Publish/Subscribe)模式、模型-视图(Model/View)模式、源-监听器(Source/Listener)模式或从属者(Dependents)模式。观察者模式是一种对象行为型模式。--摘自图说设计模式

首先,提出本文的几个问题
1.什么是观察者模式?
2.RecyclerViewAdapter.notifyDataSetChanged为什么能刷新页面?
3.RecyclerView中的观察者,在哪里注册和注销的?


什么是观察者模式?
可能对于部分初学者来说,还不是很清楚观察者设计模式是什么,那么接下来我会举个小例子来描述下观察者模式
被观察者
一个被观察者会对应多个观察者,观察者都会集合到这里,等待有变化时遍历通知观察者

public interface IObservable<U, T> {
    void registerObserver(T observer);

    void unRegisterObserver(T observer);

    void userUpdate(U user);
}
public class Observable<U, T extends Observer<U>> implements IObservable<U, T> {
    private List<T> observers;

    public Observable() {
        observers = new ArrayList<>();
    }

    @Override
    public void registerObserver(T observer) {
        observers.add(observer);//所有的观察者都添加到观察者集合
    }

    @Override
    public void unRegisterObserver(T observer) {
        observers.remove(observer);//取消订阅从集合中移除
    }

    @Override
    public void userUpdate(U u) {
        for (T observer : observers) {
            observer.update(u);//遍历通知观察者
        }
    }
}

观察管理类,被观察者的具体实现

public class ObserverManager {
    private static volatile ObserverManager mInstance;
    private IObservable<User, Observer<User>> observable;

    private ObserverManager() {
        observable = new Observable<>();
    }

    public static ObserverManager getInstance() {
        if (mInstance == null) {
            synchronized (ObserverManager.class) {
                if (mInstance == null) {
                    mInstance = new ObserverManager();
                }
            }
        }
        return mInstance;
    }

    public void addUpdate(User user) {
        observable.userUpdate(user);
    }

    public void registerObserver(Observer<User> observer) {
        observable.registerObserver(observer);
    }

    public void unRegisterObserver(Observer<User> observer) {
        observable.unRegisterObserver(observer);
    }
}

观察者
将MainActivity注册为观察者,实现update()方法

public class MainActivity extends AppCompatActivity implements Observer<User> {
    private TextView showTv;
    private List<User> users;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        showTv = findViewById(R.id.showTv);
        ObserverManager.getInstance().registerObserver(this);
        users = new ArrayList<>();
    }

    public void click(View view) {
        Intent intent = new Intent(MainActivity.this, SecondActivity.class);
        startActivity(intent);
    }

    @Override
    public void update(User user) {
        users.add(user);
        showTv.setText(users.toString());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        ObserverManager.getInstance().unRegisterObserver(this);
    }
}

在SecondActivity 中通知观察者

public class SecondActivity extends AppCompatActivity {
    private EditText nameEd;
    private EditText ageEd;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        nameEd = findViewById(R.id.nameEd);
        ageEd = findViewById(R.id.ageEd);
    }

    public void addUser(View view) {
        User user = new User(nameEd.getText().toString(), ageEd.getText().toString());
        ObserverManager.getInstance().addUpdate(user);
    }

    public void finishPager(View view) {
        finish();
    }
}

在SecondActivity输入名字和年龄,点击添加通知观察者,点击添加完毕关闭SecondActivity回到MainActivity


SecondActivity.png MainActivity.png

总结一下
1.观察者注册时添加到被观察者中的集合,以便被观察者遍历通知观察者
2.JDK中自带了观察者模式(被观察者Observable、观察者Observer),自带的Observerupdate方法中传递的参数类型是Object,需要强转
3.Android源码中观察者模式运用较多,在RecyclerViewListView中都有使用

回归正题

RecyclerViewAdapter.notifyDataSetChanged\color{red}{为什么能刷新页面?}
直接来到RecyclerView内部类Adapter中

 public abstract static class Adapter<VH extends ViewHolder> {
        private final AdapterDataObservable mObservable = new AdapterDataObservable();
        //此处省略了很多代码
}

可以看到在Adapter中实例化了AdapterDataObservableAdapterDataObservable继承自Observable,在Observable中实现了Adapter状态改变通知观察者的方法

static class AdapterDataObservable extends Observable<AdapterDataObserver> {
        public boolean hasObservers() {
            return !mObservers.isEmpty();
        }

        public void notifyChanged() {
           for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }

        public void notifyItemRangeChanged(int positionStart, int itemCount) {
            notifyItemRangeChanged(positionStart, itemCount, null);
        }

        public void notifyItemRangeChanged(int positionStart, int itemCount,
                @Nullable Object payload) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onItemRangeChanged(positionStart, itemCount, payload);
            }
        }

        public void notifyItemRangeInserted(int positionStart, int itemCount) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onItemRangeInserted(positionStart, itemCount);
            }
        }

        public void notifyItemRangeRemoved(int positionStart, int itemCount) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onItemRangeRemoved(positionStart, itemCount);
            }
        }

        public void notifyItemMoved(int fromPosition, int toPosition) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onItemRangeMoved(fromPosition, toPosition, 1);
            }
        }
    }

再来到RecyclerView中,可以看到在RecyclerView初始化了观察者RecyclerViewDataObserver

public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild2 {
    //此处省略了大量代码
    private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();
    //此处省略了大量代码
}

在Adapter的观察者状态改变时就会通知到观察者RecyclerViewDataObserver中的方法,在收到通知时调用了requestLayout() 方法,requestLayout()会调用到View的requestLayout()方法,然后在view中会去到ViewRootImpl中去自上而下刷新布局,RecyclerView中的布局就会被刷新

private class RecyclerViewDataObserver extends AdapterDataObserver {
        RecyclerViewDataObserver() {
        }

        @Override
        public void onChanged() {
            assertNotInLayoutOrScroll(null);
            mState.mStructureChanged = true;

            processDataSetCompletelyChanged(true);
            if (!mAdapterHelper.hasPendingUpdates()) {
                requestLayout();
            }
        }

        @Override
        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {
            assertNotInLayoutOrScroll(null);
            if (mAdapterHelper.onItemRangeChanged(positionStart, itemCount, payload)) {
                triggerUpdateProcessor();
            }
        }

        @Override
        public void onItemRangeInserted(int positionStart, int itemCount) {
            assertNotInLayoutOrScroll(null);
            if (mAdapterHelper.onItemRangeInserted(positionStart, itemCount)) {
                triggerUpdateProcessor();
            }
        }

        @Override
        public void onItemRangeRemoved(int positionStart, int itemCount) {
            assertNotInLayoutOrScroll(null);
            if (mAdapterHelper.onItemRangeRemoved(positionStart, itemCount)) {
                triggerUpdateProcessor();
            }
        }

        @Override
        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {
            assertNotInLayoutOrScroll(null);
            if (mAdapterHelper.onItemRangeMoved(fromPosition, toPosition, itemCount)) {
                triggerUpdateProcessor();
            }
        }

        void triggerUpdateProcessor() {
            if (POST_UPDATES_ON_ANIMATION && mHasFixedSize && mIsAttached) {
                ViewCompat.postOnAnimation(RecyclerView.this, mUpdateChildViewsRunnable);
            } else {
                mAdapterUpdateDuringMeasure = true;
                requestLayout();
            }
        }
    }
 @Override
    public void requestLayout() {
        if (mInterceptRequestLayoutDepth == 0 && !mLayoutFrozen) {
            super.requestLayout();
        } else {
            mLayoutWasDefered = true;
        }
    }

第三个问题
RecyclerView中的观察者,在哪里注册和注销的?

 private void setAdapterInternal(@Nullable Adapter adapter, boolean compatibleWithPrevious,
            boolean removeAndRecycleViews) {
        if (mAdapter != null) {//防止有开发者多次调用setAdapter,多次注册观察者
            mAdapter.unregisterAdapterDataObserver(mObserver);
            mAdapter.onDetachedFromRecyclerView(this);
        }
        if (!compatibleWithPrevious || removeAndRecycleViews) {
            removeAndRecycleViews();
        }
        mAdapterHelper.reset();
        final Adapter oldAdapter = mAdapter;
        mAdapter = adapter;
        if (adapter != null) {
            adapter.registerAdapterDataObserver(mObserver);//在这里注册
            adapter.onAttachedToRecyclerView(this);
        }
        if (mLayout != null) {
            mLayout.onAdapterChanged(oldAdapter, mAdapter);
        }
        mRecycler.onAdapterChanged(oldAdapter, mAdapter, compatibleWithPrevious);
        mState.mStructureChanged = true;
    }

注销

public void unregisterAdapterDataObserver(@NonNull AdapterDataObserver observer) {
            mObservable.unregisterObserver(observer);
        }

总结
文章开头的三个问题已经解答完毕。

相关文章

  • 第十三章 RecyclerView解析

    详细请看设计模式与实践 观察者模式解析 一、RecyclerView是什么 RecyclerView 比 List...

  • 观察者设计模式

    每周学点Java设计模式__观察者设计模式 本次继续更新java23中设计模式之一——观察者模式。 观察者模式(有...

  • 11.9设计模式-观察者模式-详解

    设计模式-观察者模式 观察者模式详解 观察者模式在android中的实际运用 1.观察者模式详解 2.观察者模式在...

  • RxJava设计模式与原理

    标准观察者设计模式 RxJava是一种特殊的观察者模式,首先我们先来看标准的观察者设计模式。在标准观察者模式中,存...

  • RxJava基础—观察者模式

    设计模式-观察者模式 观察者模式:观察者模式(有时又被称为发布(publish )-订阅(Subscribe)模式...

  • 设计模式-观察者模式 发布/订阅模式

    设计模式-观察者模式 发布/订阅模式 代码 观察者接口 具体的被观察者 观察者 最后定义中间 场景类 修改 由于上...

  • 设计模式之观察者模式

    设计模式之观察者模式 本篇是设计模式系列博客的第四篇,本篇主要学习设计模式中的第二个行为型模式---观察者模式。 ...

  • 观察者设计模式-RecyclerView中的观察者

    观察者模式(Observer Pattern):定义对象间的一种一对多依赖关系,使得每当一个对象状态发生改变时,其...

  • Android LifeCycle 源码学习总结

    整体设计 Lifecycle的核心设计模式就是观察者模式。 LifeCycleOwner 是被观察者,Lifecy...

  • 前端面试考点之手写系列

    1、观察者模式 观察者模式(基于发布订阅模式) 有观察者,也有被观察者。 观察者需要放到被观察者列表中,被观察者的...

网友评论

      本文标题:观察者设计模式-RecyclerView中的观察者

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