android观察者模式例子,Android编程设计模式之观察者模式实例详解

本文实例讲述了Android编程设计模式之观察者模式。分享给大家供大家参考,具体如下:

一、介绍

观察者模式是一个使用率非常高的模式,它最常用的地方是GUI系统、订阅——发布系统。因为这个模式的一个重要作用就是解耦,将被观察者和观察者解耦,使得它们之间的依赖性更小,甚至做到毫无依赖。以GUI系统来说,应用的UI具有易变性,尤其是前期随着业务的改变或者产品的需求修改,应用界面也会经常性变化,但是业务逻辑基本变化不大,此时,GUI系统需要一套机制来应对这种情况,使得UI层与具体的业务逻辑解耦,观察者模式此时就派上用场了。

二、定义

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

三、使用场景

关联行为场景,需要注意的是,关联行为是可拆分的,而不是”组合“关系。

事件多级触发场景。

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

四、观察者模式的UML类图

UML类图:

5ff104a7981d954693088b5a6fb18ebc.png

角色介绍:

Subject:抽象主题,也就是被观察者(Observable)的角色,抽象主题角色把所有观察者对象的引用保存到一个聚集里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,可以增加和删除观察者对象。

ConcreteSubject:具体主题,该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发出通知,具体主题角色又叫做具体被观察者(ConcreteObservable)角色。

Observer:抽象观察者,该角色是观察者的抽象类,它定义了一个更新接口,使得在得到主题的更改通知时更新自己。

ConcreteObserver:具体的观察者,该角色实现抽象观察者角色所定义的更新接口,以便主题的状态发生改变化时更新自身的状态。

五、简单实现

这里举一个追剧的例子,平常为了不错过最新的电视剧我们会订阅或关注这个电视剧,当电视剧更新后会第一时间推送给我们,下来就简单实现一下。

抽象观察者类:

/**

* 抽象观察者类,为所有具体观察者定义一个接口,在得到通知时更新自己

*/

public interface Observer {

/**

* 有更新

*

* @param message 消息

*/

public void update(String message);

}

抽象被观察者类:

/**

* 抽象被观察者类

*/

public interface Observable {

/**

* 推送消息

*

* @param message 内容

*/

void push(String message);

/**

* 订阅

*

* @param observer 订阅者

*/

void register(Observer observer);

}

具体的观察者类:

/**

* 具体的观察者类,也就是订阅者

*/

public class User implements Observer {

@Override

public void update(String message) {

System.out.println(name + "," + message + "更新了!");

}

// 订阅者的名字

private String name;

public User(String name) {

this.name = name;

}

}

具体的被观察者类:

/**

* 具体的被观察者类,也就是订阅的节目

*/

public class Teleplay implements Observable{

private List list = new ArrayList();//储存订阅者

@Override

public void push(String message) {

for(Observer observer:list){

observer.update(message);

}

}

@Override

public void register(Observer observer) {

list.add(observer);

}

}

实现:

public class Client {

public static void main(String[] args) {

//被观察者,这里就是用户订阅的电视剧

Teleplay teleplay = new Teleplay();

//观察者,这里就是订阅用户

User user1 = new User("小明");

User user2 = new User("小光");

User user3 = new User("小兰");

//订阅

teleplay.register(user1);

teleplay.register(user2);

teleplay.register(user3);

//推送新消息

teleplay.push("xxx电视剧");

}

}

结果:

小明,xxx电视剧更新了!

小光,xxx电视剧更新了!

小兰,xxx电视剧更新了!

由上面的代码可以看出实现了一对多的消息推送,推送消息都是依赖Observer和Observable这些抽象类,而User和Teleplay完全没有耦合,保证了订阅系统的灵活性和可扩展性。

六、Android源码中的观察者模式

1、BaseAdapter

BaseAdapter我相信大家都不陌生,在ListView的适配器中我们都是继承它。下面来简单分析分析。

BaseAdapter 部分代码:

public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {

//数据集观察者

private final DataSetObservable mDataSetObservable = new DataSetObservable();

public boolean hasStableIds() {

return false;

}

public void registerDataSetObserver(DataSetObserver observer) {

mDataSetObservable.registerObserver(observer);

}

public void unregisterDataSetObserver(DataSetObserver observer) {

mDataSetObservable.unregisterObserver(observer);

}

/**

* 当数据集变化时,通知所有观察者

*/

public void notifyDataSetChanged() {

mDataSetObservable.notifyChanged();

}

}

看看mDataSetObservable.notifyChanged()方法:

public class DataSetObservable extends Observable {

/**

* Invokes {@link DataSetObserver#onChanged} on each observer.

* Called when the contents of the data set have changed. The recipient

* will obtain the new contents the next time it queries the data set.

*/

public void notifyChanged() {

synchronized(mObservers) {

// 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();

}

}

}

}

可以看出在mDataSetObservable.notifyChanged()中遍历所有观察者,并调用他们的onChanged(),从而告知观察者发生了什么。

那么观察者怎么来的,那就是setAdapter方法,代码如下:

@Override

public void setAdapter(ListAdapter adapter) {

if (mAdapter != null && mDataSetObserver != null) {

mAdapter.unregisterDataSetObserver(mDataSetObserver);

}

resetList();

mRecycler.clear();

if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {

mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);

} else {

mAdapter = adapter;

}

mOldSelectedPosition = INVALID_POSITION;

mOldSelectedRowId = INVALID_ROW_ID;

// AbsListView#setAdapter will update choice mode states.

super.setAdapter(adapter);

if (mAdapter != null) {

mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();

mOldItemCount = mItemCount;

mItemCount = mAdapter.getCount();

checkFocus();

mDataSetObserver = new AdapterDataSetObserver();

mAdapter.registerDataSetObserver(mDataSetObserver);//注册观察者

......省略

}

}

AdapterDataSetObserver定义在ListView的父类AbsListView中,是一个数据集观察者,代码:

class AdapterDataSetObserver extends AdapterView.AdapterDataSetObserver {

@Override

public void onChanged() {

super.onChanged();

if (mFastScroller != null) {

mFastScroller.onSectionsChanged();

}

}

@Override

public void onInvalidated() {

super.onInvalidated();

if (mFastScroller != null) {

mFastScroller.onSectionsChanged();

}

}

}

它由继承自AbsListView的父类AdapterView的AdapterDataSetObserver, 代码如下 :

class AdapterDataSetObserver extends DataSetObserver {

private Parcelable mInstanceState = null;

// 上文有说道,调用Adapter的notifyDataSetChanged的时候会调用所有观察者的onChanged方法,核心实现就在这里

@Override

public void onChanged() {

mDataChanged = true;

mOldItemCount = mItemCount;

// 获取Adapter中数据的数量

mItemCount = getAdapter().getCount();

// Detect the case where a cursor that was previously invalidated has

// been repopulated with new data.

if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null

&& mOldItemCount == 0 && mItemCount > 0) {

AdapterView.this.onRestoreInstanceState(mInstanceState);

mInstanceState = null;

} else {

rememberSyncState();

}

checkFocus();

// 重新布局ListView、GridView等AdapterView组件

requestLayout();

}

// 代码省略

public void clearSavedState() {

mInstanceState = null;

}

}

当ListView的数据发生变化时,调用Adapter的notifyDataSetChanged函数,这个函数又会调用DataSetObservable的notifyChanged函数,这个函数会调用所有观察者 (AdapterDataSetObserver) 的onChanged方法。这就是一个观察者模式!

七、总结

优点:

观察者和被观察者之间是抽象耦合,应对业务变化。

增强系统的灵活性和可扩展性。

缺点:

在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。

希望本文所述对大家Android程序设计有所帮助。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值