观察者模式与监听器机制

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里去,注册的方法是调用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(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();

        }

    }

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值