(转)ListView BaseAdapter中的观察者模式

来源:互联网 发布:网络摄像机检测报告 编辑:程序博客网 时间:2024/06/07 01:25

原地址:http://blog.csdn.net/fancylovejava/article/details/49947697


Android SDK源码中用到了很多开发模式,其中BaseAdapter就属于观察者模式


[java] view plain copy
  1. public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {  
  2.     private final DataSetObservable mDataSetObservable = new DataSetObservable();  
  3.   
  4.     public boolean hasStableIds() {  
  5.         return false;  
  6.     }  
  7.       
  8.     public void registerDataSetObserver(DataSetObserver observer) {  
  9.         mDataSetObservable.registerObserver(observer);  
  10.     }  
  11.   
  12.     public void unregisterDataSetObserver(DataSetObserver observer) {  
  13.         mDataSetObservable.unregisterObserver(observer);  
  14.     }  

中有DataSetObservable可被观察到的对象即被观察对象,这个对象将观察者对象加入到自己的观察者对象集中

[java] view plain copy
  1. public abstract class Observable<T> {  
  2.     /** 
  3.      * The list of observers.  An observer can be in the list at most 
  4.      * once and will never be null. 
  5.      */  
  6.     protected final ArrayList<T> mObservers = new ArrayList<T>();  
  7.   
  8.     /** 
  9.      * Adds an observer to the list. The observer cannot be null and it must not already 
  10.      * be registered. 
  11.      * @param observer the observer to register 
  12.      * @throws IllegalArgumentException the observer is null 
  13.      * @throws IllegalStateException the observer is already registered 
  14.      */  
  15.     public void registerObserver(T observer) {  
  16.         if (observer == null) {  
  17.             throw new IllegalArgumentException("The observer is null.");  
  18.         }  
  19.         synchronized(mObservers) {  
  20.             if (mObservers.contains(observer)) {  
  21.                 throw new IllegalStateException("Observer " + observer + " is already registered.");  
  22.             }  
  23.             mObservers.add(observer);  
  24.         }  
  25.     }  

每次改变ListView的数据的时候,需要notifyDataSetChanged,这个实现是 mDataSetObservable.notifyChanged();

被观察者对象调用方法

[java] view plain copy
  1. public class DataSetObservable extends Observable<DataSetObserver> {  
  2.     /** 
  3.      * Invokes {@link DataSetObserver#onChanged} on each observer. 
  4.      * Called when the contents of the data set have changed.  The recipient 
  5.      * will obtain the new contents the next time it queries the data set. 
  6.      */  
  7.     public void notifyChanged() {  
  8.         synchronized(mObservers) {  
  9.             // since onChanged() is implemented by the app, it could do anything, including  
  10.             // removing itself from {@link mObservers} - and that could cause problems if  
  11.             // an iterator is used on the ArrayList {@link mObservers}.  
  12.             // to avoid such problems, just march thru the list in the reverse order.  
  13.             for (int i = mObservers.size() - 1; i >= 0; i--) {  
  14.                 mObservers.get(i).onChanged();  
  15.             }  
  16.         }  
  17.     }  
然后观察者对象在onChanged方法中去处理。

还有个问题,registerDataSetObserver(DataSetObserver observer)什么时候被调用的

看源码发现原来是在ListView的setAdapter方法中调用的

[java] view plain copy
  1. @Override  
  2.    public void setAdapter(ListAdapter adapter) {  
  3.        if (mAdapter != null && mDataSetObserver != null) {  
  4.            mAdapter.unregisterDataSetObserver(mDataSetObserver);  
  5.        }  
  6.   
  7.        resetList();  
  8.        mRecycler.clear();  
  9.   
  10.        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {  
  11.            mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);  
  12.        } else {  
  13.            mAdapter = adapter;  
  14.        }  
  15.   
  16.        mOldSelectedPosition = INVALID_POSITION;  
  17.        mOldSelectedRowId = INVALID_ROW_ID;  
  18.   
  19.        // AbsListView#setAdapter will update choice mode states.  
  20.        super.setAdapter(adapter);  
  21.   
  22.        if (mAdapter != null) {  
  23.            mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();  
  24.            mOldItemCount = mItemCount;  
  25.            mItemCount = mAdapter.getCount();  
  26.            checkFocus();  
  27.   
  28.            mDataSetObserver = new AdapterDataSetObserver();  
  29.            mAdapter.registerDataSetObserver(mDataSetObserver);  
  30.   
  31.            mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());  
  32.   
  33.            int position;  
  34.            if (mStackFromBottom) {  
  35.                position = lookForSelectablePosition(mItemCount - 1false);  
  36.            } else {  
  37.                position = lookForSelectablePosition(0true);  
  38.            }  
  39.            setSelectedPositionInt(position);  
  40.            setNextSelectedPositionInt(position);  
  41.   
  42.            if (mItemCount == 0) {  
  43.                // Nothing selected  
  44.                checkSelectionChanged();  
  45.            }  
  46.        } else {  
  47.            mAreAllItemsSelectable = true;  
  48.            checkFocus();  
  49.            // Nothing selected  
  50.            checkSelectionChanged();  
  51.        }  
  52.   
  53.        requestLayout();  
  54.    }  

看到里面初始化了一个对象AdapterDataSetObserver,这个对象在AbsListView里的内部类

[java] view plain copy
  1. class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {  
  2.        @Override  
  3.        public void onChanged() {  
  4.            super.onChanged();  
  5.            if (mFastScroll != null) {  
  6.                mFastScroll.onSectionsChanged();  
  7.            }  
  8.        }  
  9.   
  10.        @Override  
  11.        public void onInvalidated() {  
  12.            super.onInvalidated();  
  13.            if (mFastScroll != null) {  
  14.                mFastScroll.onSectionsChanged();  
  15.            }  
  16.        }  
  17.    }  

实现了具体的onChanged方法,好了,基本理清楚Adapter里面怎么通知更新数据了。


但是上面有个FastScroller对象,这个类找了半天没找到在哪,在GC上搜说在android.widget包下,但是并没有。

有知道是为什么得吗?麻烦请教一下!


最后补充看RecycleView的源码,里面也是观察者模式,但是整体感觉RecycleView比ListView更好!有空可以学习学习


0 0
原创粉丝点击