Android源码分析:Android中的设计模式——观察者模式

Android源码分析:Android中的设计模式——观察者模式

转载请注明出处:http://blog.csdn.net/qq_1050087728/article/details/69663729

题记

Android源码中有很多经典的设计模式,本文重点讨论Android源码中的观察者模式。在开发中经常会用到的MVC(Model-View-Controller)框架设计模式就是观察者模式的一个实例。当模型的数据发生变化时,能够发出通知更新UI界面中的数据,使得UI界面中的数据与模型数据保持一致。观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生改变时,会通知所有的观察者对象,使他们能够自动更新自己。欲详细了解 观察者模式 请点击Java设计模式-观察者模式
了解了观察者模式的概念以后,接下来以Android开发中经常用到的ListView、RecyclerView、Spinner等控件的使用为例,来说明在Android中所使用的观察者模式。Android中通过适配器Adapter(通常继承自BaseAdapter)来将模型数据与视图进行绑定(其中用到了适配器模式),在抽象类BaseAdaper中有个notifyDataSetChanged()的方法,当adapter的源数据发生变化时,adapter调用此方法,可以实现UI中数据的刷新,从而使得模型数据能够和UI中展示的数据保持一致的状态。按照这个逻辑,顺藤摸瓜来看一看在android中是如何利用观察者模式来实现这一功能的。

BaseAdapter源码分析


package android.widget;

import android.database.DataSetObservable;
import android.database.DataSetObserver;
import android.view.View;
import android.view.ViewGroup;

/**
 * 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 boolean hasStableIds() {
        return false;
    }

    public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
    }

    public void unregisterDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.unregisterObserver(observer);
    }

    /**
     * Notifies the attached observers that the underlying data has been changed
     * and any View reflecting the data set should refresh itself.
     */
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }

    /**
     * Notifies the attached observers that the underlying data is no longer valid
     * or available. Once invoked this adapter is no longer valid and should
     * not report further data set changes.
     */
    public void notifyDataSetInvalidated() {
        mDataSetObservable.notifyInvalidated();
    }

    public boolean areAllItemsEnabled() {
        return true;
    }

    public boolean isEnabled(int position) {
        return true;
    }

    public View getDropDownView(int position, View convertView, ViewGroup parent) {
        return getView(position, convertView, parent);
    }

    public int getItemViewType(int position) {
        return 0;
    }

    public int getViewTypeCount() {
        return 1;
    }

    public boolean isEmpty() {
        return getCount() == 0;
    }
}

BaseAdapter中持有一个DataSetObservable对象mDataSetObservable,并实现了方法registerDataSetObserver,unregisterDataSetObserver,notifyDataSetChanged,notifyDataSetInvalidated,非常类似于Subject(主题)的功能,方法内部mDataSetObservable调用了DataSetObserverable的方法:

注册观察者:mDataSetObservable.registerObserver(observer);
注销观察者:mDataSetObservable.unregisterObserver(observer);
通知观察者改变:mDataSetObservable.notifyChanged();
通知观察者失效:mDataSetObservable.notifyInvalidated();

这不就是观察者模式吗,DataSetObservable是具体的主题DataSetObserver是该主题的观察者
下面具体看看DataSetObservable类的代码。

DataSetObservable源码分析

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.database;

/**
 * A specialization of {@link Observable} for {@link DataSetObserver}
 * that provides methods for sending notifications to a list of
 * {@link DataSetObserver} objects.
 */
public class DataSetObservable extends Observable<DataSetObserver> {
    /**
     * Invokes {@link DataSetObserver#onChanged} on each observer.
     * Called when the contents of the data set have changed.  The recipient
     * will obtain the new contents the next time it queries the data set.
     */
    public void notifyChanged() {
        synchronized(mObservers) {
            // since onChanged() is implemented by the app, it could do anything, including
            // removing itself from {@link mObservers} - and that could cause problems if
            // an iterator is used on the ArrayList {@link mObservers}.
            // to avoid such problems, just march thru the list in the reverse order.
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onChanged();
            }
        }
    }

    /**
     * Invokes {@link DataSetObserver#onInvalidated} on each observer.
     * Called when the data set is no longer valid and cannot be queried again,
     * such as when the data set has been closed.
     */
    public void notifyInvalidated() {
        synchronized (mObservers) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                mObservers.get(i).onInvalidated();
            }
        }
    }
}

DataSetObservable是抽象主题Observable的具体实现,是一个具体的主题。它是为观察者DataSetObserver而定义的,提供了将通知发送到DataSetObserver类型的观察者列表。通知观察者改变notifyChanged()和通知观察者无效notifyInvalidated()。

下面看抽象主题Observable的源码,如下:

Observable源码分析

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.database;

import java.util.ArrayList;

/**
 * Provides methods for registering or unregistering arbitrary observers in an {@link ArrayList}.
 *
 * This abstract class is intended to be subclassed and specialized to maintain
 * a registry of observers of specific types and dispatch notifications to them.
 *
 * @param T The observer type.
 */
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>();

    /**
     * Adds an observer to the list. The observer cannot be null and it must not already
     * be registered.
     * @param observer the observer to register
     * @throws IllegalArgumentException the observer is null
     * @throws IllegalStateException the observer is already registered
     */
    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);
        }
    }

    /**
     * Removes a previously registered observer. The observer must not be null and it
     * must already have been registered.
     * @param observer the observer to unregister
     * @throws IllegalArgumentException the observer is null
     * @throws IllegalStateException the observer is not yet registered
     */
    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);
        }
    }

    /**
     * Remove all registered observers.
     */
    public void unregisterAll() {
        synchronized(mObservers) {
            mObservers.clear();
        }
    }
}

这个抽象主题类提供了在ArrayList中注册或注销任意观察者的方法。该抽象类旨在被子类化,它的子类专门用于维护特定类型的观察者的注册表并向他们发送通知。
在本例中,子类DataSetObservable主题用于维护DataSetObserver类型的观察者的注册表并向他们发送通知。

接下来,再来看看观察者DataSetObserver的源码

DataSetObserver源码分析

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.database;

/**
 * Receives call backs when a data set has been changed, or made invalid. The typically data sets
 * that are observed are {@link Cursor}s or {@link android.widget.Adapter}s.
 * DataSetObserver must be implemented by objects which are added to a DataSetObservable.
 */
public abstract class DataSetObserver {
    /**
     * This method is called when the entire data set has changed,
     * most likely through a call to {@link Cursor#requery()} on a {@link Cursor}.
     */
    public void onChanged() {
        // Do nothing
    }

    /**
     * This method is called when the entire data becomes invalid,
     * most likely through a call to {@link Cursor#deactivate()} or {@link Cursor#close()} on a
     * {@link Cursor}.
     */
    public void onInvalidated() {
        // Do nothing
    }
}

定义了一个抽象观察者DataSetObserver,数据集已更改或无效时接收回调。 观察到的典型数据集是光标或适配器。 DataSetObserver必须由添加到DataSetObservable的对象来实现。

至此,分析完了一个Android中数据设置的观察者模式示例,其抽象主题是package android.database中的Obsevable,具体主题是DataSetObservable,观察者是DataSetObserver

Android API中的主题和观察者

Android 中大量采用了观察者模式,那么Android中有多少主题和观察者呢?在Android Developer 中可以查看具体的API文档。
首先查询主题,输入关键词Observable,查询结果如下
Android中的Observable

从结果中可以看到,主要有三大类抽象主题:

1)android.database.Observable:安卓数据库包中的主题Observable,上述示例的Observable就是这个主题。

2)android.util.Observable:安卓帮助包中的主题Observable。

3)android.databinding.Observable:安卓数据绑定包中主题Observable。其子类主题有许多,都和数据绑定有关。主要是一些集合和数据类型绑定的主题,如ObservableArrayList,ObservableInt。除此之外还有变量绑定主题ObservableField,序列绑定主题ObservableParcelable,属性改变回调主题Observable.OnPropertyChangedCallback等。

查询观察者Observer,查询结果如下
Android中的Observer
从结果可以看出,Android中主要有三大类观察者

1)java.util.Observer: 帮助类观察者;

2)android.database.xxxObserver: 数据库包下的观察者; 如数据设置观察者DataSetObserver ;

3)android.os.FileObserver :文件观察者;

4)android.content.xxxObserver :内容观察者,如同步状态观察者SyncStatusObserver;

5)android.app.backup.RestoreObserver: app后台恢复观察者;

6)android.view.ViewTreeObserver: 视图树的观察者及其子观察者,应用最为广泛,几乎所有的UI工具都会用到该观察者模式。在android的UI界面系统中用的特别多,被广泛用在MVC架构模式中。

转载请注明出处:http://blog.csdn.net/qq_1050087728/article/details/69663729

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值