- 浏览: 205280 次
- 性别:
- 来自: 南京
文章分类
最新评论
-
xyyx_nk:
在demo中没有下载的示例,能详细说一下怎么监听下载过程吗?比 ...
DhNet 网络http工具(带缓存功能哦) -dhroid文档 -
zhaoguowei998:
dhroid ioc模块对 加密混淆问题 -
zhaoguowei998:
你太牛了,佩服佩服,以后要多想你请教了
dhroid ioc模块对 加密混淆问题 -
白色蜻蜓:
转载下您的文章,已注明出处。
IOS开发之百度地图API应用 -
wenjiefeng:
你好,在andrioidpn-client客户端源码里,Not ...
Android 推送之原理与初触Androidpn(Android Push Notification)
1、 观察者模式与监听器机制
1.1 观察者模式
The observer pattern (a subset of the publish/subscribe pattern) is a software design pattern in which an object, called the subject, maintains a list of its dependents, called observers, and notifies them automatically of any state changes, usually by calling one of their methods. It is mainly used to implement distributed event handling systems.
l The Java Swing library makes extensive use of the observer pattern for event management
l The Java Servlet API is heavily using observer pattern to notify application entities about significant events, observed by web container. Listeners are provided for servlet and session lifecycle, session migration, changes to scoped attributes etc.
l PerfectJPattern Open Source Project, Provides a context-free and type-safe implementation of the Observer Pattern in Java.
1.2 监听器(Listener)机制
代码的基本框架:
* 被监控着
package com.wonders.group;
import java.util.Collection;
public class ModelTie {
private Collection<Object> dataSet;
public interface DataSetSupervioer {
public void onChange();
}
private DataSetSupervioer dataSetChangeListener;
public void setDataSetChangeListener(DataSetSupervioer dataSetChangeListener) {
this.dataSetChangeListener = dataSetChangeListener;
}
public void notifyDataSetChange() {
if (null != dataSetChangeListener) {
dataSetChangeListener.onChange();
}
}
public Collection<Object> getDataSet() {
return dataSet;
}
public ModelTie setDataSet(Collection<Object> dataSet) {
this.dataSet = dataSet;
this.notifyDataSetChange(); // 数据设置完毕要通知监听器进行更新操作
return this;
}
}
* 监控者
package com.wonders.group;
import java.util.Collection;
import java.util.Iterator;
import com.wonders.group.ModelTie.DataSetSupervioer;
public class PresentationTie {
private ModelTie model;
public PresentationTie() {
super();
// 添加监听器
model.setDataSetChangeListener(new DataSetSupervioer() {
public void onChange() {
// 填写一些前置操作,如更新数据
DisplayModel(); // 重新绘制
// 填写一些后置操作,如更新状态
}
});
}
public void DisplayModel() {
Collection<Object> collection = model.getDataSet();
if (collection != null) {
for (Iterator iterator = collection.iterator(); iterator.hasNext();) {
System.out.println(((Object) iterator.next()).toString());
// 其他等等操作
}
}
}
public ModelTie getModel() {
return model;
}
public void setModel(ModelTie model) {
this.model = model;
}
}
2、 ArrayAdapter的观察者实现机制
以下仅罗列关键代码:
public class ArrayAdapter<T> extends BaseAdapter implements Filterable {
private boolean mNotifyOnChange = true;
/**
* Adds the specified object at the end of the array.
*/
public void add(T object) {
if (mOriginalValues != null) {
synchronized (mLock) {
mOriginalValues.add(object);
if (mNotifyOnChange) notifyDataSetChanged();
}
} else {
mObjects.add(object);
if (mNotifyOnChange) notifyDataSetChanged();
}
}
/**
* Inserts the specified object at the specified index in the array.
*/
public void insert(T object, int index) {
if (mOriginalValues != null) {
synchronized (mLock) {
mOriginalValues.add(index, object);
if (mNotifyOnChange) notifyDataSetChanged();
}
} else {
mObjects.add(index, object);
if (mNotifyOnChange) notifyDataSetChanged();
}
}
/**
* Removes the specified object from the array.
*/
public void remove(T object) {
if (mOriginalValues != null) {
synchronized (mLock) {
mOriginalValues.remove(object);
}
} else {
mObjects.remove(object);
}
if (mNotifyOnChange) notifyDataSetChanged();
}
/**
* Remove all elements from the list.
*/
public void clear() {
if (mOriginalValues != null) {
synchronized (mLock) {
mOriginalValues.clear();
}
} else {
mObjects.clear();
}
if (mNotifyOnChange) notifyDataSetChanged();
}
/**
* Sorts the content of this adapter using the specified comparator.
*/
public void sort(Comparator<? super T> comparator) {
Collections.sort(mObjects, comparator);
if (mNotifyOnChange) notifyDataSetChanged();
}
@Override
public void notifyDataSetChanged() {
super.notifyDataSetChanged(); // 关键代码,这个notifyDataSetChanged()是从父类BaseAdapter继承过来的,所以看看在父类中它干了些什么
mNotifyOnChange = true;
}
}
/**
* Common base class of common implementation for an {@link Adapter} that can be
* used in both {@link ListView} (by implementing the specialized
* {@link ListAdapter} interface} and {@link Spinner} (by implementing the
* specialized {@link SpinnerAdapter} interface.
*/
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
private final DataSetObservable mDataSetObservable = new DataSetObservable();
public void registerDataSetObserver(DataSetObserver observer) {
mDataSetObservable.registerObserver(observer);
}
public void unregisterDataSetObserver(DataSetObserver observer) {
mDataSetObservable.unregisterObserver(observer);
}
/**
* Notifies the attached View that the underlying data has been changed
* and it should refresh itself.
*/
public void notifyDataSetChanged() {
mDataSetObservable.notifyChanged(); // 关键代码:说明调的是成员变量mDataSetObservable的方法,所以进入DataSetObservable看看具体是如何操作的
}
public void notifyDataSetInvalidated() {
mDataSetObservable.notifyInvalidated();
}
}
package android.database;
/**
* A specialization of Observable for DataSetObserver that provides methods for
* invoking the various callback methods of DataSetObserver.
*/
public class DataSetObservable extends Observable<DataSetObserver> {
/**
* Invokes onChanged on each observer. Called when the data set being observed has
* changed, and which when read contains the new state of the data.
*/
public void notifyChanged() {
synchronized(mObservers) {
for (DataSetObserver observer : mObservers) { // 这里的mObservers是哪来的呢?继续追踪,但首先可以判断是来自Observable<DataSetObserver>的。进入看看
observer.onChanged();
}
}
}
/**
* Invokes onInvalidated on each observer. Called when the data set being monitored
* has changed such that it is no longer valid.
*/
public void notifyInvalidated() {
synchronized (mObservers) {
for (DataSetObserver observer : mObservers) {
observer.onInvalidated();
}
}
}
}
public abstract class Observable<T> {
/**
* The list of observers. An observer can be in the list at most
* once and will never be null.
*/
protected final ArrayList<T> mObservers = new ArrayList<T>();
public void registerObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
if (mObservers.contains(observer)) {
throw new IllegalStateException("Observer " + observer + " is already registered.");
}
mObservers.add(observer);
}
}
public void unregisterObserver(T observer) {
if (observer == null) {
throw new IllegalArgumentException("The observer is null.");
}
synchronized(mObservers) {
int index = mObservers.indexOf(observer);
if (index == -1) {
throw new IllegalStateException("Observer " + observer + " was not registered.");
}
mObservers.remove(index);
}
}
public void unregisterAll() {
synchronized(mObservers) {
mObservers.clear();
}
}
}
对于DataSetObserver基类,我们也给出代码:
public abstract class DataSetObserver {
public void onChanged() {}
public void onInvalidated() {}
}
综合起来分析就是,ArrayAdapter使自己具备被观察的能力的方法是,ArrayAdapter内部有一个private final DataSetObservable mDataSetObservable = new DataSetObservable()的变量,这个变量一方面维护着一个保存观察者的数据结构,另一方面提供registerDataSetObserver(DataSetObserver observer)和unregisterDataSetObserver(DataSetObserver observer)来管理观察自己的对象;而当ArrayAdapter绑定数的据发生变化时,它会调用内部的notifyDataSetChanged()方法,但这个方法最终是调用mDataSetObservable的notifyChanged()方法。在该方法里,该方法会逐一审视有哪些观察者在观察我,然后调用观察者的观察方法onChanged()。
3、 ListView观察ArrayAdapter的数据集的机制
通过以上分析可以知道,ListView要实现观察ArrayAdapter,需要将自己注册到ArrayAdapter的DataSetObservable mDataSetObservable里去,注册的方法是调用ArrayAdapter的registerDataSetObserver(DataSetObserver observer)方法。
那ListView是如何将自己注册上去的呢?具体过程如下:
public class ListView extends AbsListView {
/**
* Sets the data behind this ListView.
*
* The adapter passed to this method may be wrapped by a {@link WrapperListAdapter},
* depending on the ListView features currently in use. For instance, adding
* headers and/or footers will cause the adapter to be wrapped.
*
* @param adapter The ListAdapter which is responsible for maintaining the
* data backing this list and for producing a view to represent an
* item in that data set.
*/
@Override
public void setAdapter(ListAdapter adapter) {
if (null != mAdapter) {
mAdapter.unregisterDataSetObserver(mDataSetObserver); // 关键的成员变量,继承自AbsListView,等下去看看AbsListView关于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;
if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
mOldItemCount = mItemCount;
mItemCount = mAdapter.getCount();
checkFocus();
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver); // 在这里进行注册,注册为数据集的观察员
mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
int position;
if (mStackFromBottom) {
position = lookForSelectablePosition(mItemCount - 1, false);
} else {
position = lookForSelectablePosition(0, true);
}
setSelectedPositionInt(position);
setNextSelectedPositionInt(position);
if (mItemCount == 0) {
// Nothing selected
checkSelectionChanged();
}
if (mChoiceMode != CHOICE_MODE_NONE &&
mAdapter.hasStableIds() &&
mCheckedIdStates == null) {
mCheckedIdStates = new LongSparseArray<Boolean>();
}
} else {
mAreAllItemsSelectable = true;
checkFocus();
// Nothing selected
checkSelectionChanged();
}
if (mCheckStates != null) {
mCheckStates.clear();
}
if (mCheckedIdStates != null) {
mCheckedIdStates.clear();
}
requestLayout();
}
}
public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher,
ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,
ViewTreeObserver.OnTouchModeChangeListener {
/**
* Should be used by subclasses to listen to changes in the dataset
*/
AdapterDataSetObserver mDataSetObserver; // mDataSetObserver就是在这里定义的。那我们再看看AdapterDataSetObserver是什么类型的数据,看看当数据发生变化的时候,该类会进行什么样的动作。
/**
* The adapter containing the data to be displayed by this view
*/
ListAdapter mAdapter;
}
值得注意的是,AdapterDataSetObserver是AdapterView里的一个内部类(http://www.androidjavadoc.com/1.1_r1_src/android/widget/class-use/AdapterView.AdapterDataSetObserver.html ),具体我们查看下代码:
class AdapterDataSetObserver extends DataSetObserver {
private Parcelable mInstanceState = null;
@Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
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();
requestLayout(); // 这里是关键:这就是为什么数据发生了变化,视图可以随之变换的原因,因为它会调用框架,来进行重新绘制。最终调用的代码看紧接着的代码
}
@Override
public void onInvalidated() {
mDataChanged = true;
if (AdapterView.this.getAdapter().hasStableIds()) {
// Remember the current state for the case where our hosting activity is being
// stopped and later restarted
mInstanceState = AdapterView.this.onSaveInstanceState();
}
// Data is invalid so we should reset our state
mOldItemCount = mItemCount;
mItemCount = 0;
mSelectedPosition = INVALID_POSITION;
mSelectedRowId = INVALID_ROW_ID;
mNextSelectedPosition = INVALID_POSITION;
mNextSelectedRowId = INVALID_ROW_ID;
mNeedSync = false;
checkSelectionChanged();
checkFocus();
requestLayout();
}
public void clearSavedState() {
mInstanceState = null;
}
}
最终调用的代码(from View.class)
/**
* Call this when something has changed which has invalidated the
* layout of this view. This will schedule a layout pass of the view
* tree.
*/
public void requestLayout() {
if (ViewDebug.TRACE_HIERARCHY) {
ViewDebug.trace(this, ViewDebug.HierarchyTraceType.REQUEST_LAYOUT);
}
mPrivateFlags |= FORCE_LAYOUT;
if (mParent != null && !mParent.isLayoutRequested()) {
mParent.requestLayout();
}
}
发表评论
-
关于android WebViewClient的方法解释
2012-09-09 17:12 7691、public boolean shouldOverride ... -
android 缩放图片与内存溢出
2012-08-03 09:43 1220常用的Android版缩放图片代码: ContentRes ... -
获取手机设备方向
2012-08-03 09:33 1464@Override public void onS ... -
activity四种启动模式
2012-08-03 09:30 808Activity 有四种加载模式 [1] standa ... -
Activity启动模式singleTask,singleInstance研究
2012-08-03 09:26 846Activity的四种启动模式是相当重要的知识点,给activ ... -
[Android分享] Android 得到已安装的应用程序信息
2012-06-20 14:42 824我们大家都知道在手机上我们可以查看图标来知道我们都安装 ... -
Android开发中的小技术
2012-06-14 17:12 8401.WebView加载各种类型的网页 ? ... -
Androidpn的框架浅析
2012-06-11 22:16 964开发部署方法: 1 ... -
用androidpn来实现推送
2012-06-11 22:08 1084关于服务器端向Android ... -
Android 推送之原理与初触Androidpn(Android Push Notification)
2012-06-11 22:06 3706由于最近项目中涉及到 ... -
Androidpn分析
2012-06-11 22:04 1107原文:http://xgeek.me/blog/201 ... -
HorizontalScrollView 嵌套 listView 的问题
2012-05-29 19:41 2405这是一个假命题 HorizontalScroll ... -
android:shape的使用
2012-05-26 18:31 859Android 中常常使用shape来定义控件的一些显 ... -
android百度地图 问题解决
2012-05-23 19:24 1379用百度地图移动API,添加覆盖物图层,然后将一些兴趣点标注在覆 ... -
Android学习笔记之地图(根据地名查询经纬度)
2012-05-23 19:07 1338Android 通过地名获得经纬度并标识在地图上 ... -
Android编程获取手机型号,本机电话号码,sdk版本及firmware版本号(即系统版本号)
2012-05-23 19:01 2063Android开发平台中,可通过TelephonyMan ... -
android 代码混淆问题
2012-05-23 13:56 1071今天项目进行代码混淆时一直出现apk可安装但是不可运行,搞了一 ... -
popupwindow 显示和消失的动画
2012-05-12 17:20 3222前段时间搞android 动画,在页面中使用动画后效果还 ... -
android-【DDMS->heap->MAT】工具-内存分析工具
2012-05-12 16:12 1505使用heap dump来追踪这个问题。点击DDMS工具条 ... -
webview 的使用
2012-05-03 17:10 941在Android手机中内置了一款高性能webkit内核浏 ...
相关推荐
这样,当按钮被点击(事件发生)时,不仅会执行监听器中的动作,还可以更新其他依赖于这个事件的状态,符合观察者模式的定义。 在实际项目中,监听机制和观察者设计模式常用于构建响应式的用户界面、实现业务逻辑的...
在JavaBean中,虽然没有直接与观察者模式相关的特定类或接口,但JavaBean规范允许开发者创建可序列化、属性可访问的组件。这些组件可以通过属性变更事件(PropertyChangeSupport)支持观察者模式。例如,开发者可以...
观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在Java中,这种模式被广泛应用于事件处理,例如JavaBeans事件。 JavaBeans...
在Java中,我们可以利用Java提供的内置监听器机制来实现观察者模式,例如`ApplicationListener`和`ApplicationEvent`,这两个类主要用于Swing或JavaFX应用程序中的事件处理。 首先,我们来看`ApplicationListener`...
观察者模式,也被称为发布-订阅(Publish-Subscribe)模式,是软件设计模式中的行为模式之一,它在对象间定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。...
观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在C++中,这种模式经常用于游戏开发,特别是在像cocos2d-x这样的2D游戏引擎...
本文将深入分析观察者模式的组成部分和应用场景,并探讨Java事件处理机制的原理,以及事件源、事件、监听器与观察者设计模式中各角色的对应关系。 观察者模式的组成部分包括被观察者(Subject)和观察者(Observer...
观察者模式有多种变体,如发布/订阅模式、模型-视图-控制器(MVC)架构中的模型与视图之间的关系,以及Java的事件监听机制等。 综上所述,观察者模式是软件设计中的重要工具,它通过引入一种间接的依赖关系,使得...
在iOS中,我们可以利用Apple的Foundation框架中的NSNotification机制来实现观察者模式。NSNotification中心负责广播通知,而对象可以注册为观察者,监听特定的通知并作出响应。 1. 创建通知中心...
观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在软件工程中,这种模式被广泛应用于事件驱动编程和异步通信中。在这个主题...
观察者模式的这种实现方式使得OECP社区能够灵活地扩展功能,因为新的事件类型和监听器可以轻松地加入到系统中,而不会对现有代码造成过多的影响。同时,这种模式也支持了系统的模块化,每个模块只需要关注自己的职责...
在编程领域,事件机制和观察者模式是两个重要的概念,特别是在ActionScript 3(AS3)中被广泛应用。本文将详细探讨这两个主题,以及如何在AS3中实现一个基于观察者模式的事件处理机制。 首先,事件机制是编程中一种...
这体现了观察者模式的核心思想:主体与观察者之间的松耦合。 在实际的编程实现中,观察者模式通常包括以下几个关键组件: 1. **主题(Subject)**:这是被观察的对象,它可以是任何类型的对象,包含可以更改的状态...
例如,在Web开发中,可以使用观察者模式处理用户交互事件,当用户触发某个操作时,相关的监听器(观察者)会得到通知并执行相应的逻辑。 总的来说,HeadFirst设计模式的学习笔记2关于观察者模式的演示,旨在帮助...
在Android开发中,回调模式和观察者模式是两种常见的事件处理机制,它们在软件设计模式中扮演着重要的角色,主要用于实现组件之间的通信。本文将详细探讨这两种模式,并结合Android环境进行解析。 首先,我们来理解...
### 观察者模式设计详解 #### 概述 观察者模式是一种常用的设计模式,用于定义对象间的依赖关系。...在框架开发中,事件监听器也是观察者模式的具体体现。掌握观察者模式对于提高软件设计的质量和灵活性具有重要意义。
观察者模式是一种行为设计模式,它允许你定义一个订阅机制,可以发布事件到多个订阅者,即观察者。这些观察者会在特定事件发生时自动接收通知。这种模式促进了松耦合,使得主题(被观察的对象)和观察者之间可以独立...
Java事件处理机制,如AWT和Swing中的事件监听,也是基于观察者模式。例如,按钮点击事件就是一个典型的例子,按钮(事件源)是观察目标,而监听按钮点击的事件处理器(事件监听器)就是观察者。 **观察者模式与MVC*...
观察者模式通常用于实现实时更新和通知机制,在各种应用领域都有广泛的应用,如图形用户界面(GUI)、消息订阅系统、事件驱动系统等。 #### 二、观察者模式的角色与结构 观察者模式主要涉及四个角色: 1. **抽象...
观察者模式是软件设计模式中的一种行为模式,它在对象之间定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式广泛应用于事件驱动编程、发布/订阅系统...