`

观察者模式与监听器机制

 
阅读更多

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.

 

The Java Swing library makes extensive use of the observer pattern for event management

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.

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()方法,但这个方法最终是调用mDataSetObservablenotifyChanged()方法。在该方法里,该方法会逐一审视有哪些观察者在观察我,然后调用观察者的观察方法onChanged()

3、 ListView观察ArrayAdapter的数据集的机制

通过以上分析可以知道,ListView要实现观察ArrayAdapter,需要将自己注册到ArrayAdapterDataSetObservable mDataSetObservable里去,注册的方法是调用ArrayAdapterregisterDataSetObserver(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(mHeaderViewInfosmFooterViewInfos, 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;

}

值得注意的是,AdapterDataSetObserverAdapterView里的一个内部类(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();

        }

    }

  • 大小: 34.1 KB
分享到:
评论

相关推荐

    java中监听机制,以及观察者设计模式

    这样,当按钮被点击(事件发生)时,不仅会执行监听器中的动作,还可以更新其他依赖于这个事件的状态,符合观察者模式的定义。 在实际项目中,监听机制和观察者设计模式常用于构建响应式的用户界面、实现业务逻辑的...

    设计模式:观察者模式java和javabean

    在JavaBean中,虽然没有直接与观察者模式相关的特定类或接口,但JavaBean规范允许开发者创建可序列化、属性可访问的组件。这些组件可以通过属性变更事件(PropertyChangeSupport)支持观察者模式。例如,开发者可以...

    观察者模式与JavaBeans事件

    观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在Java中,这种模式被广泛应用于事件处理,例如JavaBeans事件。 JavaBeans...

    观察者模式java实现观察者设计模式

    在Java中,我们可以利用Java提供的内置监听器机制来实现观察者模式,例如`ApplicationListener`和`ApplicationEvent`,这两个类主要用于Swing或JavaFX应用程序中的事件处理。 首先,我们来看`ApplicationListener`...

    观察者模式最佳实践

    观察者模式,也被称为发布-订阅(Publish-Subscribe)模式,是软件设计模式中的行为模式之一,它在对象间定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并被自动更新。...

    c++观察者模式实例

    观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在C++中,这种模式经常用于游戏开发,特别是在像cocos2d-x这样的2D游戏引擎...

    观察者模式在Java事件处理中的应用研究.pdf

    本文将深入分析观察者模式的组成部分和应用场景,并探讨Java事件处理机制的原理,以及事件源、事件、监听器与观察者设计模式中各角色的对应关系。 观察者模式的组成部分包括被观察者(Subject)和观察者(Observer...

    java23种设计模式之观察者模式

    观察者模式有多种变体,如发布/订阅模式、模型-视图-控制器(MVC)架构中的模型与视图之间的关系,以及Java的事件监听机制等。 综上所述,观察者模式是软件设计中的重要工具,它通过引入一种间接的依赖关系,使得...

    IOS 观察者模式实例Demo

    在iOS中,我们可以利用Apple的Foundation框架中的NSNotification机制来实现观察者模式。NSNotification中心负责广播通知,而对象可以注册为观察者,监听特定的通知并作出响应。 1. 创建通知中心...

    观察者模式学习

    观察者模式(Observer Pattern)是一种行为设计模式,它允许你定义一个订阅机制,可以在对象状态改变时通知多个“观察”该对象的其他对象。在软件工程中,这种模式被广泛应用于事件驱动编程和异步通信中。在这个主题...

    社区事件驱动机制-观察者模式实用

    观察者模式的这种实现方式使得OECP社区能够灵活地扩展功能,因为新的事件类型和监听器可以轻松地加入到系统中,而不会对现有代码造成过多的影响。同时,这种模式也支持了系统的模块化,每个模块只需要关注自己的职责...

    事件机制 观察者模式

    在编程领域,事件机制和观察者模式是两个重要的概念,特别是在ActionScript 3(AS3)中被广泛应用。本文将详细探讨这两个主题,以及如何在AS3中实现一个基于观察者模式的事件处理机制。 首先,事件机制是编程中一种...

    观察者模式Observer

    这体现了观察者模式的核心思想:主体与观察者之间的松耦合。 在实际的编程实现中,观察者模式通常包括以下几个关键组件: 1. **主题(Subject)**:这是被观察的对象,它可以是任何类型的对象,包含可以更改的状态...

    HeadFirst 设计模式学习笔记2--观察者模式 demo

    例如,在Web开发中,可以使用观察者模式处理用户交互事件,当用户触发某个操作时,相关的监听器(观察者)会得到通知并执行相应的逻辑。 总的来说,HeadFirst设计模式的学习笔记2关于观察者模式的演示,旨在帮助...

    Android监听——回调模式与观察者模式

    在Android开发中,回调模式和观察者模式是两种常见的事件处理机制,它们在软件设计模式中扮演着重要的角色,主要用于实现组件之间的通信。本文将详细探讨这两种模式,并结合Android环境进行解析。 首先,我们来理解...

    观察者模式设计

    ### 观察者模式设计详解 #### 概述 观察者模式是一种常用的设计模式,用于定义对象间的依赖关系。...在框架开发中,事件监听器也是观察者模式的具体体现。掌握观察者模式对于提高软件设计的质量和灵活性具有重要意义。

    js观察者模式列子js观察者模式列子

    观察者模式是一种行为设计模式,它允许你定义一个订阅机制,可以发布事件到多个订阅者,即观察者。这些观察者会在特定事件发生时自动接收通知。这种模式促进了松耦合,使得主题(被观察的对象)和观察者之间可以独立...

    Java设计模式-第22章-观察者模式.ppt

    Java事件处理机制,如AWT和Swing中的事件监听,也是基于观察者模式。例如,按钮点击事件就是一个典型的例子,按钮(事件源)是观察目标,而监听按钮点击的事件处理器(事件监听器)就是观察者。 **观察者模式与MVC*...

    设计模式之观察者模式.pdf

    观察者模式通常用于实现实时更新和通知机制,在各种应用领域都有广泛的应用,如图形用户界面(GUI)、消息订阅系统、事件驱动系统等。 #### 二、观察者模式的角色与结构 观察者模式主要涉及四个角色: 1. **抽象...

    软件设计模式:观察者模式.zip

    观察者模式是软件设计模式中的一种行为模式,它在对象之间定义了一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都会得到通知并自动更新。这种模式广泛应用于事件驱动编程、发布/订阅系统...

Global site tag (gtag.js) - Google Analytics