2000字范文,分享全网优秀范文,学习好帮手!
2000字范文 > Android设计模式--观察者模式

Android设计模式--观察者模式

时间:2019-03-23 00:56:01

相关推荐

Android设计模式--观察者模式

一、概述

1.1观察者模式介绍

观察者模式是一个使用频率非常高的模式,他最常用的地方是GUI系统和订阅-发布系统。

该模式的最重要的作用就是解耦,使观察者和被观察者之间依赖尽可能小,甚至好无依赖。

1.2观察者模式的定义

定义对象间一种一对多的关系,使得每当一个对象改版状态,所有依赖它的对象都会得到通知并更新。

如图:

1.3观察者模式的使用场景

1.事件多级触发场景

2.关联行为场景

3.跨系统的消息交换场景,如:消息队列,事件总线的处理机制

举几个简单的例子说明一下:

例一:生活中,我们一群人围着锅吃饭,饭好了,我们就开吃。(观察者:人们,被观察者:饭)例二:Android中,最常见的点击事件,通过设置控件的OnClickListener并传入一个OnClickListener的实现类来回调点击事件。(观察者:OnClickListener,被观察者:控件)例三:Android中,我们从A页面–>B页面–>C页面–>D页面–>F页面… 我们想把A页面信息传递给最后一个页面,如果通过页面传递那么很繁琐,我们直接可以在需要的页面去订阅A页面的事件,当A页面刷行数据,其他订阅了A页面事件的就可以直接接受数据。(相当于少了中间商赚差价,是不爽了很多,而且效率还比较高)例四:Android中,我们常用的recyclerView,listView刷行数据时调用notifyDataSetChanged()来更新ui,想知道具体原因,那么请仔细往下看完这篇文章。例五:Android中,我们通常发送一个广播,凡是注册了该广播的都可以接收到该广播,这也是Android中典型的观察者模式。

1.4观察者模式的UML

Subject:抽象主题,把所有观察者对象的引用保持再一个集合,每个主题可以有多个观察者(一对多)。

ConcreteSubject:具体主题,在内部发生变化是后,通知所有注册过的观察者。

Observer:抽象观察者,定义了一个更新接口,得到主题更改通知的时候更新自己。

ConcreteObserver:具体的观察者,实现了抽象观察者的更新接口,以便在主题状态发生变化时候更新自身状态。

二、简单实现

我们假设开发一款新闻的软件,每当有新的内容推出,那么只要是订阅了该新闻的用户都可以接收到该新闻。

这种模式叫做发布–订阅模式,也称为观察者模式。

demo下载地址:/download/github_33304260/10146740

首先我们需要完成被观察者,这里新闻网站是被观察对象。

/*** Created by doudou on /12/5.** 新闻网站----被观察者*/public class News extends Observable{public void postNewPublication(String content){//标识状态或者内容发送改变setChanged();//通知所有观察者notifyObservers(content);}}

然后去完成观察者:

/*** Created by doudou on /12/5.** 订阅新闻的用户-----观察者*/public class User implements Observer{public String name;public MainActivity activity;private String msg;public User(String name, MainActivity activity) {this.name = name;this.activity = activity;}@Overridepublic void update(Observable observable, Object o) {String news = "Hi,"+name+",发布新内容啦!!"+o;Log.e("binli",news);}}

接着我们就可以发布新闻啦!

news = new News();//观察者user_one = new User("用户一",this);user_two = new User("用户二",this);user_three = new User("用户三",this);news.addObserver(user_one);news.addObserver(user_two);news.addObserver(user_three);news.postNewPublication("重大新闻,新的一期Android技术前线周报发布啦!!!");

Observer和Observable是JDK中的内置类型,可以看出观察者模式的重要性。在这里***Observer***是***抽象的观察者***,***user***是具体的观察者;***Observable***是抽象的主题,***News***是具体的主题。

当User订阅了News之后,当News有更新,就会去遍历所有观察者(User),然后给每一个观察者更新信息,即调用User的update()方法,这样就完成了一对多的通知功能。

在这个过程中,完全依赖Observer和Observable,对于User和News完全没有耦合,保证了订阅的灵活性和可扩展性。

三深入理解

3.1RecycleView的观察者模式

RecycleView最重要的一个功能就是Adapter,当我们向RecycleView中添加数据后,都会调用notifyDataSetChanged()方法,这是为什么呢,今天来一探究竟。

我们先看adapter.notifyDataSetChanged()函数

public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild {//代码省略public static abstract class Adapter<VH extends ViewHolder> {private final AdapterDataObservable mObservable = new AdapterDataObservable();//代码省略public final void notifyDataSetChanged() {mObservable.notifyChanged();}//代码省略}//代码省略static class AdapterDataObservable extends Observable<AdapterDataObserver> {public boolean hasObservers() {return !mObservers.isEmpty();}/*** 数据集观察者*/public void notifyChanged() {/*** 调用每个观察者的onChanged函数来通知他们被观察者发生了变化*/for (int i = mObservers.size() - 1; i >= 0; i--) {mObservers.get(i).onChanged();}}//代码省略}}

从上面的代码我们可以看出来,当我们调用adapter.notifyDataSetChanged()时,实际在遍历所有的观察者,并调用他们的onChanged方法,从而告诉观察者发生了变化。

那么问题来了,这些观察者从哪里来的?

其实这些观察者是在setAdapter时候产生的。我们看下相关代码:

public class RecyclerView extends ViewGroup implements ScrollingView, NestedScrollingChild {private final RecyclerViewDataObserver mObserver = new RecyclerViewDataObserver();//代码省略public void setAdapter(Adapter adapter) {//代码省略setAdapterInternal(adapter, false, true);//代码省略}private void setAdapterInternal(Adapter adapter, boolean compatibleWithPrevious,boolean removeAndRecycleViews) {/***如果已经有了一个adapter,那么先注销该Adapter的对应的观察者*/if (mAdapter != null) {mAdapter.unregisterAdapterDataObserver(mObserver);mAdapter.onDetachedFromRecyclerView(this);}//代码省略mAdapterHelper.reset();final Adapter oldAdapter = mAdapter;mAdapter = adapter;if (adapter != null) {/*** 将这个观察者注册到Adapter中,实际上是注册到AdapterDataObserver*/adapter.registerAdapterDataObserver(mObserver);adapter.onAttachedToRecyclerView(this);}//代码省略}//代码省略private class RecyclerViewDataObserver extends AdapterDataObserver {/*** 上面说过调用Adapter的notifyDataSetChanged时调用所有观察者的onChange方法,核心就是在这实现的。* 重新设置Flag,然后重新跟新布局*/@Overridepublic void onChanged() {assertNotInLayoutOrScroll(null);if (mAdapter.hasStableIds()) {mState.mStructureChanged = true;setDataSetChangedAfterLayout();} else {mState.mStructureChanged = true;setDataSetChangedAfterLayout();}if (!mAdapterHelper.hasPendingUpdates()) {requestLayout();}}//代码省略}//代码省略}

到这里我们知道,当RecycleView数据发生变化时,调用AdapternotifyDataSetChanged函数,该函数会调用AdapterDataObservablenotifyChanged函数,这个函数会调用所有观察者(RecyclerViewDataObserver)的onChanged方法,然后所有观察者会重新绘制布局。

这就是一个观察者模式。

扫码关注公众号“伟大程序猿的诞生“,更多干货新鲜文章等着你~

公众号回复“资料获取”,获取更多干货哦~

有问题添加本人微信号“fenghuokeji996” 或扫描博客导航栏本人二维码

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。