Android 手机卫士15--程序锁
1.观察者模式模式简介
定义:
观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态变化时,会通知所有的观察者对象,使他们能够自动更新自己。
观察者模式结构图:
- Subject:抽象主题(抽象被观察者),抽象主题角色把所有观察者对象保存在一个集合里,每个主题都可以有任意数量的观察者,抽象主题提供一个接口,可以增加和删除观察者对象。
- ConcreteSubject:具体主题(具体被观察者),该角色将有关状态存入具体观察者对象,在具体主题的内部状态发生改变时,给所有注册过的观察者发送通知。
- Observer:抽象观察者,是观察者者的抽象类,它定义了一个更新接口,使得在得到主题更改通知时更新自己。
- ConcrereObserver:具体观察者,是实现抽象观察者定义的更新接口,以便在得到主题更改通知时更新自身的状态。
2.观察者模式简单实现
观察者模式这种发布-订阅的形式我们可以拿微信公众号来举例,假设微信用户就是观察者,微信公众号是被观察者,有多个的微信用户关注了程序猿这个公众号,当这个公众号更新时就会通知这些订阅的微信用户。好了我们来看看用代码如何实现:
抽象观察者(Observer)
里面定义了一个更新的方法:
public interface Observer {
public void update(String message);
}
具体观察者(ConcrereObserver)
微信用户是观察者,里面实现了更新的方法:
public class WeixinUser implements Observer {
// 微信用户名
private String name;
public WeixinUser(String name) {
this.name = name;
}
@Override
public void update(String message) {
System.out.println(name + "-" + message);
} }
抽象被观察者(Subject)
抽象主题,提供了attach、detach、notify三个方法:
public interface Subject {
/**
* 增加订阅者
* @param observer
*/
public void attach(Observer observer);
/**
* 删除订阅者
* @param observer
*/
public void detach(Observer observer);
/**
* 通知订阅者更新消息
*/
public void notify(String message);
}
具体被观察者(ConcreteSubject)
微信公众号是具体主题(具体被观察者),里面存储了订阅该公众号的微信用户,并实现了抽象主题中的方法:
public class SubscriptionSubject implements Subject {
//储存订阅公众号的微信用户
private List<Observer> weixinUserlist = new ArrayList<Observer>(); @Override
public void attach(Observer observer) {
weixinUserlist.add(observer);
} @Override
public void detach(Observer observer) {
weixinUserlist.remove(observer);
} @Override
public void notify(String message) {
for (Observer observer : weixinUserlist) {
observer.update(message);
}
}
}
客户端调用
public class Client {
public static void main(String[] args) {
SubscriptionSubject mSubscriptionSubject=new SubscriptionSubject();
//创建微信用户
WeixinUser user1=new WeixinUser("杨影枫");
WeixinUser user2=new WeixinUser("月眉儿");
WeixinUser user3=new WeixinUser("紫轩");
//订阅公众号
mSubscriptionSubject.attach(user1);
mSubscriptionSubject.attach(user2);
mSubscriptionSubject.attach(user3);
//公众号更新发出消息给订阅的微信用户
mSubscriptionSubject.notify("刘望舒的专栏更新了");
}
} 结果: 杨影枫-刘望舒的专栏更新了
月眉儿-刘望舒的专栏更新了
紫轩-刘望舒的专栏更新了
3.使用观察者模式的场景和优缺点
使用场景
- 关联行为场景,需要注意的是,关联行为是可拆分的,而不是“组合”关系。
- 事件多级触发场景。
- 跨系统的消息交换场景,如消息队列、事件总线的处理机制。
优点
解除耦合,让耦合的双方都依赖于抽象,从而使得各自的变换都不会影响另一边的变换。
缺点
在应用观察者模式时需要考虑一下开发效率和运行效率的问题,程序中包括一个被观察者、多个观察者,开发、调试等内容会比较复杂,而且在Java中消息的通知一般是顺序执行,那么一个观察者卡顿,会影响整体的执行效率,在这种情况下,一般会采用异步实现。
4.Android中的观察者模式
android源码中也有很多使用了观察者模式,比如OnClickListener、ContentObserver、android.database.Observable等;还有组件通讯库RxJava、RxAndroid、EventBus;在这里将拿我们最常用的Adapter的notifyDataSetChanged()方法来举例:
当我们用ListView的时候,数据发生变化的时候我们都会调用Adapter的notifyDataSetChanged()方法,这个方法定义在BaseAdaper中,我们来看看BaseAdaper的部分源码:
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();
}
很明显BaseAdapter用的是观察者模式,BaseAdapter是具体被观察者,接下来看看mDataSetObservable.notifyChanged():
public class DataSetObservable extends Observable<DataSetObserver> {
public void notifyChanged() {
synchronized(mObservers) {
for (int i = mObservers.size() - ; i >= ; i--) {
mObservers.get(i).onChanged();
}
}
}
我们看到了mObservers,这就是观察者的集合,这些观察者是在ListView通过setAdaper()设置Adaper时产生的:
@Override
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
...
super.setAdapter(adapter); if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
mOldItemCount = mItemCount;
mItemCount = mAdapter.getCount();
checkFocus();
//创建数据观察者
mDataSetObserver = new AdapterDataSetObserver();
//注册观察者
mAdapter.registerDataSetObserver(mDataSetObserver); ...
}
接下来看看观察者AdapterDataSetObserver中处理了什么:
class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
@Override
public void onChanged() {
super.onChanged();
if (mFastScroller != null) {
mFastScroller.onSectionsChanged();
}
} @Override
public void onInvalidated() {
super.onInvalidated();
if (mFastScroller != null) {
mFastScroller.onSectionsChanged();
}
}
}
从上面的代码看不出什么,再看看AdapterDataSetObserver的父类AdapterView的AdapterDataSetObserver:
class AdapterDataSetObserver extends DataSetObserver {
private Parcelable mInstanceState = null;
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount();
if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == && mItemCount > ) {
AdapterView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
//重新布局
requestLayout();
} ... public void clearSavedState() {
mInstanceState = null;
}
}
我们看到在onChanged()方法中调用了requestLayout()方法来重新进行布局。好了,看到这里我们都明白了,当ListView的数据发生变化时,我们调用Adapter的notifyDataSetChanged()方法,这个方法又会调用观察者们(AdapterDataSetObserver)的onChanged()方法,onChanged()方法又会调用requestLayout()方法来重新进行布局。
“标准答案”:观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。观察者模式完美的将观察者和被观察的对象分离开,一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。
回调函数其实也算是一种观察者模式的实现方式,回调函数实现的观察者和被观察者往往是一对一的依赖关系。
所以最明显的区别是观察者模式是一种设计思路,而回调函数式一种具体的实现方式;另一明显区别是一对多还是多对多的依赖关系方面。
Android 手机卫士15--程序锁的更多相关文章
- [android] 手机卫士设备管理权限锁屏
设备管理员 Device Admin 获取DevicePolicyManager对象,通过getSystemService(DEVICE_POLICY_MANAGER),设备策略管理器 调用Devic ...
- [android] 手机卫士应用程序更新和签名
弹出升级对话框 获取AlertDialog.Builder对象,通过new出来 调用Builder对象的setTitle()方法,参数:文本 调用Builder对象的setMessage()方法,参数 ...
- Android 手机卫士--弹出对话框
在<Android 手机卫士--解析json与消息机制发送不同类型消息>一文中,消息机制发送不同类型的信息还没有完全实现,在出现异常的时候,应该弹出吐司提示异常,代码如下: private ...
- android手机卫士、3D指南针、动画精选、仿bilibli客户端、身份证银行卡识别等源码
Android精选源码 android身份证.银行卡号扫描源码 android仿bilibili客户端 android一款3D 指南针 源码 android手机卫士app源码 android提醒应用, ...
- Android 手机卫士--参照文档编写选择器
本文来实现<Android 手机卫士--导航界面1的布局编写>中的图片选择器部分的代码. 本文地址:http://www.cnblogs.com/wuyudong/p/5944356.ht ...
- Android 手机卫士--设置界面&功能列表界面跳转逻辑处理
在<Android 手机卫士--md5加密过程>中已经实现了加密类,这里接着实现手机防盗功能 本文地址:http://www.cnblogs.com/wuyudong/p/5941959. ...
- Android 手机卫士--确认密码对话框编写
本文接着实现“确认密码”功能,也即是用户以前设置过密码,现在只需要输入确认密码 本文地址:http://www.cnblogs.com/wuyudong/p/5940718.html,转载请注明出处. ...
- Android 手机卫士--签名文件说明&包名说明
在<Android 手机卫士--打包生成apk维护到服务器>一文中,实现了新版本的apk到服务器,当打开客户端apk的时候,发现有新版本,提示更新.还实现了利用xutils工具实现了从服务 ...
- Android项目实战--手机卫士24--程序锁的实现以及逻辑
昨天我们已经把程序全部读取出来,显示到界面上了,那今天,我们就来讲一下那个程序锁的实现啦.其实也很简单啦,我们主要就是把用户要锁定的程序放到一个表里面,然后就监听手机里面的任务栈,如果发现任务栈里面出 ...
随机推荐
- 分布式并行数据库将在OLTP 领域促进去“Oracle”
原文链接:http://www.csdn.net/article/2015-09-11/2825678 摘要:本文全面介绍了分布式数据库和它的设计理念,以及分布式数据库的优势和应用场景,从而引出OLT ...
- 那些年我们赚过的外快(POS(移动支付)接口开发)
老规矩上前戏了.在我写博文"那些年我们赚过的外快"前后算起来大大小小也接了些私活,这次是因为好久没写博客了,趁热分享一下.最近回了离老家近的二线城市成都工作,收入那是下降很多啊,刚 ...
- 项目演化系列--验证体系(基于angular的前端验证)
前言 之前分享的<web项目演化--验证体系>中提到基于angular的验证,但是为了以防读者迷惑,能够好的理解验证体系,所以没有详细介绍. 今天特地补写一篇关于构建angular的验证. ...
- Linux下U盘变成只读
今天用Ubuntu给同学拷贝数据的时候,突然其中一个文件夹U盘就不能复制和删除了.再windows7下可以删除除修改的那个文件夹之外的数据,但修改的那个文件夹死活删除不掉,只读属性也去不掉.再Ubun ...
- NHibernate 使用CreateSQLQuery进行查询
涉及的表:Cake{Id ,CakeName } CakeSize{ CakeId,-为外键,对应Cake表的字段Id Size } (其中ISession session = NHibernateH ...
- Linux高级编程--07.进程间通信
每个进程各自有不同的用户地址空间,进程之间要交换数据必须通过在内核中开辟缓冲区,从而实现数据共享. 管道 管道是一种最基本的IPC机制,由pipe函数创建: int pipe(int filedes[ ...
- JS思维之路菜鸟也能有大能量-序幕
准备写一类关于Js的开发思想的文章,这系列文章需要有一定的js基础,在这里不会去说太多的js基础知识,因为这系列文章不是写基础东西,而是一种编程思想,如果你还是js新手,那么建议你有一定基础后再看. ...
- Container Stack
- DDD:Strategic Domain Driven Design with Context Mapping
Introduction Many approaches to object oriented modeling tend not to scale well when the application ...
- jQuery+Ajax滚屏异步加载数据实现(附源码)
一.CSS样式 body { font:12px/1.0em Microsoft Yahei; line-height:1.6em; background:#fff; line-height:1.2e ...