博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android进阶系列--源码分析观察者模式在ListView的运用
阅读量:4165 次
发布时间:2019-05-26

本文共 5652 字,大约阅读时间需要 18 分钟。

源码是谷歌攻城狮的精髓,我们要向他们学习,提高自己,只能翱翔于源码的海洋,才能明白谷歌攻城狮的强大。观察者在我们开发过程中使用的是相当的多,那么在源码层就使用的更多了。之前有做过观察者模式的学习笔记。这里就不重复一遍了

      观察者模式定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态上发生变化时,会通知所有观察者对象,使它们能够自动更新自己。

  • 抽象主题(Subject)角色:抽象主题角色把所有对观察者对象的引用保存在一个聚集(比如ArrayList对象)里,每个主题都可以有任何数量的观察者。抽象主题提供一个接口,
    可以增加和删除观察者对象,抽象主题角色又叫做抽象被观察者(Observable)角色。
  • 具体主题(ConcreteSubject)角色:将有关状态存入具体观察者对象;在具体主题的内部状态改变时,给所有登记过的观察者发出通知。具体主题角色又叫做具体被观察者(Concrete Observable)角色。
  • 抽象观察者(Observer)角色:为所有的具体观察者定义一个接口,在得到主题的通知时更新自己,这个接口叫做更新接口。
  • 具体观察者(ConcreteObserver)角色:存储与主题的状态自恰的状态。具体观察者角色实现抽象观察者角色所要求的更新接口,以便使本身的状态与主题的状态 像协调。如果需要,具体观察者角色可以保持一个指向具体主题对象的引用。

public class MainActivity extends AppCompatActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ListView listView = new ListView(this);        MyAdapter myAdapter = new MyAdapter();        //注册观察者        listView.setAdapter(myAdapter);        //这里通知观察者更新数据        myAdapter.notifyDataSetChanged();    }    private class MyAdapter extends BaseAdapter{        @Override        public int getCount() {            return 0;        }        @Override        public Object getItem(int position) {            return null;        }        @Override        public long getItemId(int position) {            return 0;        }        @Override        public View getView(int position, View convertView, ViewGroup parent) {            return null;        }    }}

我们在使用ListView的时候,一般是这样使用的。那么我们先从setAdapter开始。看看是如何注册观察者的。

@Override    public void setAdapter(ListAdapter adapter) {        if (mAdapter != null && mDataSetObserver != null) {            mAdapter.unregisterDataSetObserver(mDataSetObserver);        }        resetList();        mRecycler.clear();        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {            mAdapter = wrapHeaderListAdapterInternal(mHeaderViewInfos, mFooterViewInfos, adapter);        } else {            mAdapter = adapter;        }        mOldSelectedPosition = INVALID_POSITION;        mOldSelectedRowId = INVALID_ROW_ID;        // AbsListView#setAdapter will update choice mode states.        super.setAdapter(adapter);        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();            }        } else {            mAreAllItemsSelectable = true;            checkFocus();            // Nothing selected            checkSelectionChanged();        }        requestLayout();    }
mDataSetObserver = new AdapterDataSetObserver();mAdapter.registerDataSetObserver(mDataSetObserver);创建了一个观察者,并且注册了。注册方法里的逻辑是什么呢。registerDataSetObserver调用的BaseAdapter的。

private final DataSetObservable mDataSetObservable = new DataSetObservable();    public void registerDataSetObserver(DataSetObserver observer) {        mDataSetObservable.registerObserver(observer);    }

BaseAdapterregisterDataSetObserver中,创建了一个被观察者对象,调用被观察者的registerObserver进行绑定。

/**     * 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);        }    }
mObservers是一个集合,用于存观察者。进行管理,这里就是一对多的关系建立。注册完成之后,那么我们什么时候通知观察者更新数据呢?就是调用notifyDataChanged的时候。在BaseAdapter中,查看notifyDataChanged

/**     * 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();    }
继续在DataSetObservable中,查看notifyChanged

/**     * 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();            }        }    }
对存储的观察进行遍历,依次通知观察者进行更新,调用onChanged。那么观察者在ListView中的使用就这么多,当然ListView中使用的设计模式很多,还有像模板方法等等。有兴趣的可以自己研究研究。

转载地址:http://duqxi.baihongyu.com/

你可能感兴趣的文章
Spring MVC和Struts2的比较
查看>>
Hibernate和IBatis对比
查看>>
Spring MVC 教程,快速入门,深入分析
查看>>
Android 的source (需安装 git repo)
查看>>
LOCAL_PRELINK_MODULE和prelink-linux-arm.map
查看>>
Ubuntu Navicat for MySQL安装以及破解方案
查看>>
Class.forName( )你搞懂了吗?——转
查看>>
jarFile
查看>>
EJB与JAVA BEAN_J2EE的异步消息机制
查看>>
数学等于号是=那三个横杠是什么符
查看>>
HTTP协议详解
查看>>
java多线程中的join方法详解
查看>>
idea添加gradle模块报错The project is already registered
查看>>
在C++中如何实现模板函数的外部调用
查看>>
HTML5学习之——HTML 5 拖放
查看>>
HTML5学习之——HTML 5 Canvas vs. SVG
查看>>
HTML5学习之——HTML 5 应用程序缓存
查看>>
HTML5学习之——HTML 5 Web Workers
查看>>
HTML5学习之——HTML 5 Canvas
查看>>
HTML5学习之——HTML5 内联 SVG
查看>>