registerDataSetObserver:浅析Andorid ListView和Adapte

最近由于遇到将内容分部绑定到ListView里的需求,追踪源码之后对ListView和Adapter有了点肤浅的认识,在此与大家分享。

这里用到了观察者模式,在ListView的setAdapter里注册一个AdapterDataSetObserver观察者。

  1. public void setAdapter(ListAdapter adapter) {
  2. ........
  3. mDataSetObserver = new AdapterDataSetObserver();//AdapterDataSetObserver是ListView的基类AdapterView的内部类
  4. mAdapter.registerDataSetObserver(mDataSetObserver);//注册一个观察者
  5. .........
  6. requestLayout();//更新视图
  7. }

ListAdapter是一接口,BaseAdapter继承了它

  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.     }
  15.      
  16.     /**
  17.      * Notifies the attached observers that the underlying data has been changed
  18.      * and any View reflecting the data set should refresh itself.
  19.      */
  20.     public void notifyDataSetChanged() {
  21.         mDataSetObservable.notifyChanged();
  22.     }
  23.  
  24.     /**
  25.      * Notifies the attached observers that the underlying data is no longer valid
  26.      * or available. Once invoked this adapter is no longer valid and should
  27.      * not report further data set changes.
  28.      */
  29.     public void notifyDataSetInvalidated() {
  30.         mDataSetObservable.notifyInvalidated();
  31.     }
  32.  
  33.     public boolean areAllItemsEnabled() {
  34.         return true;
  35.     }
  36.  
  37.     public boolean isEnabled(int position) {
  38.         return true;
  39.     }
  40.  
  41.     public View getDropDownView(int position, View convertView, ViewGroup parent) {
  42.         return getView(position, convertView, parent);
  43.     }
  44.  
  45.     public int getItemViewType(int position) {
  46.         return 0;
  47.     }
  48.  
  49.     public int getViewTypeCount() {
  50.         return 1;
  51.     }
  52.      
  53.     public boolean isEmpty() {
  54.         return getCount() == 0;
  55.     }
  56. }

DataSetObservable定义如下:

  1. public class DataSetObservable extends Observable<DataSetObserver> {
  2.     public void notifyChanged() {//通知每个观察者数据已变化
  3.         synchronized(mObservers) {
  4.             for (DataSetObserver observer : mObservers) {
  5.                 observer.onChanged();
  6.             }
  7.         }
  8.     }
  9.  
  10.     public void notifyInvalidated() {
  11.         synchronized (mObservers) {
  12.             for (DataSetObserver observer : mObservers) {
  13.                 observer.onInvalidated();
  14.             }
  15.         }
  16.     }
  17. }

ListView里注册的观察者是AdapterDataSetObserver对象,其定义如下:

  1. class AdapterDataSetObserver extends DataSetObserver {
  2.  
  3.         private Parcelable mInstanceState = null;
  4.  
  5.         @Override
  6.         public void onChanged() {
  7.             mDataChanged = true;
  8.             mOldItemCount = mItemCount;
  9.             mItemCount = getAdapter().getCount();//Adapter现有元素个数
  10.  
  11.             if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
  12.                     && mOldItemCount == 0 && mItemCount > 0) {
  13.                 AdapterView.this.onRestoreInstanceState(mInstanceState);
  14.                 mInstanceState = null;
  15.             } else {
  16.                 rememberSyncState();
  17.             }
  18.             checkFocus();
  19.             requestLayout();//更新视图
  20.         }
  21. .................
  22. }

AdapterDataSetObserver里的具体实现我没弄清楚,但感觉是在这里更新了ListView显示的数据,ListView里是怎样更新的没弄清楚,希望哪位高手知道的告诉我。

但是如果只在ListView里显示Adapter的部分数据,该怎么弄呢,可继承BaseAdapter,实现BaseAdapter里未实现的如下方法:

getCount()、getItem(int position)、getItemId(int position)、getView(int position, View convertView, ViewGroup parent)。

只需在getCount里返回想要的大小就行了。

原文地址:https://www.cnblogs.com/feng9exe/p/9253704.html