Android 中的监听器模式与观察者模式

摘要:
=Null){对于{System.out.println;//其他操作}}}}publicModelTiegetModel(){returnmodel;}publicvoisetModel{this.model=model;}}}2。ArrayAdapter的观察器实现机制如下:publicclassArrayAdapterextendsBaseAdaptrimplementsFilterable{privatepoolenNotifyOnChange=true;/**在数组末尾添加指定的对象。*/publicvoid Add{if(mOriginalValues!

1、   观察者模式与监听器机制

1.1 观察者模式

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) {

这对方法用来注册或注销

观察ArrayAdapter的观察者的

 

        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 中的监听器模式与观察者模式》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ng4.0 生命周期『重构--改善既有代码的设计』读书笔记----代码坏味道【3】下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

widget 常用UI控件介绍

    一、单选框 单选框实例程序:<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_pa...

ZK框架笔记5、事件

        事件是org.zkoss.zk.ui.event.Event类,它通知应用程序发生了什么事情。每一种类型的事件都由一个特定的类来表示。         要响应一个事件,应用程序必须为事件注册一个或更多事件监听器。有3种方式可以为一个组件事件监听器。   (1)一般制定onXXX事件监听器为组件的属性,作为属性定义的事件监听器。 &...

spring kafka消费者配置介绍----ackMode

当 auto.commit.enable 设置为false时,表示kafak的offset由customer手动维护,spring-kafka提供了通过ackMode的值表示不同的手动提交方式; ackMode有以下7种值: public enum AckMode { // 当每一条记录被消费者监听器(ListenerConsumer)处理...

XD 05

项目启动方式 1. 在 springBoot application 上右键 run as Java application 2. run as mvn install 会打包一个jar 包 3. war 在 tomcat, war 包方式, 一般 springBoot 都是使用 jar 包启动了 a. 首先在 pom 文件中添加 <packagin...

angular问题总结

已经用angular开发了大概有三个月了,开始两周很艰难,慢慢的也渐渐熟悉一些了。在此整理一下这段时间遇到的各种坑。 一、Angular怎样停止请求(1)首先在需要请求的controller中注入$q服务, (2)在scope变量中声明一个变量,var canceler; (3)在事件最上方写上 //取消之前的请求 if (canceler) cancel...

JMeter学习(八)JDBC测试计划-连接Oracle(转载)

转载自 http://www.cnblogs.com/yangxia-test 一.测试环境准备       Oracle:10g       JDBC驱动:classes12.jar                              oracle安装目录下(oracleproduct10.2.0db_1jdbclibclasses12.jar)文...