ListView设置Adapter和更新数据源码分析--观察者模式

  当我们使用ListView控件的时候,其中最重要的一个功能是使用Adapter,我们一般会使用BaseAdapter。通常,我们向ListView添加数据后,都会调用Adapter的notifyDataSetChanged()方法。
  接下来的分析使用的是安卓8.0的源码,以下为接下来用到的代码的路径;

  • base/core/java/android/widget/AdapterView.java(抽象类,继承自ViewGroup)
public abstract class AdapterView<T extends Adapter> extends ViewGroup{
    //省略代码;
}
  • base/core/java/android/widget/AbsListView.java
public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher,
        ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,
        ViewTreeObserver.OnTouchModeChangeListener,
        RemoteViewsAdapter.RemoteAdapterConnectionCallback {
    //省略代码;
}
  • base/core/java/android/widget/ListView.java
public class ListView extends AbsListView {
    //省略代码;
}
  • base/core/java/android/widget/Adapter.java(接口)
public interface Adapter {
    //省略代码;
}
  • base/core/java/android/widget/ListAdapter.java(接口,继承了Adapter接口)
public interface ListAdapter extends Adapter {
    //省略代码;
}
  • base/core/java/android/widget/SpinnerAdapter.java(接口,继承了Adapter接口)
public interface SpinnerAdapter extends Adapter {
    //省略代码;
}
  • base/core/java/android/widget/BaseAdapter.java(类,实现了ListAdapter接口和SpinnerAdapter接口)
public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
    //省略代码;
}
  • base/core/java/android/database/Observable.java(抽象类)
public abstract class Observable<T> {
    //省略代码;
}
  • base/core/java/android/database/DataSetObservable.java(抽象类)
public class DataSetObservable extends Observable<DataSetObserver> {
    //省略代码;
}
  • base/core/java/android/database/DataSetObserver.java(类,继承自Observable)
public abstract class DataSetObserver {
    //省略代码;
}

源码分析

  先从BaseAdapter的notifyDataSetChanged()方法开始;

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);
    }
    
    //当数据集变化时,通知所有的观察者;
    public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }
}

  大概看了BaseAdapter的代码,就会知道BaseAdapter是一个观察者模式。接下来,我们根据mDataSetObservable.notifyChanged();来继续跟踪代码。

public class DataSetObservable extends Observable<DataSetObserver> {
    //调用每个观察者的onChanged()方法来通知它们被观察者发生了变化;
    public void notifyChanged() {
        synchronized(mObservers) {
            for (int i = mObservers.size() - 1; i >= 0; i--) {
                //调用所有观察者的onChanged()方法;
                mObservers.get(i).onChanged();
            }
        }
    }
}

  在上面的代码中,就是遍历所有观察者,并且调用它们的onChanged()方法,从而告知观察者发生了什么。这些观察者,其实就是ListView通过setAdapter()方法设置Adapter产生的。

public class ListView extends AbsListView {
    @Override
    public void setAdapter(ListAdapter adapter) {
        if (mAdapter != null && mDataSetObserver != null) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
        }
        //代码省略;
        super.setAdapter(adapter);
        
        if (mAdapter != null) {
            mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
            mOldItemCount = mItemCount;
            //获取数据的数量;
            mItemCount = mAdapter.getCount();
            checkFocus();
            //创建一个数据集观察者,这个AdapterDataSetObserver是父类中的;
            mDataSetObserver = new AdapterDataSetObserver();
            //将这个观察者注册到Adapter中,实际上是注册到DataSetObservable中;
            mAdapter.registerDataSetObserver(mDataSetObserver);

            //省略代码;
        } else {
            //省略代码;
        }

        requestLayout();
    }
}

  在设置Adapter时,会构建一个AdapterDataSetObserver,这个就是所说的被观察者。最后,将这个被观察者注册到Adapter中,这样,我们的被观察者和观察者都有了。AdapterDataSetObserver是定义在ListView的父类AbsListView中的,代码如下。

public abstract class AbsListView extends AdapterView<ListAdapter> implements TextWatcher,
        ViewTreeObserver.OnGlobalLayoutListener, Filter.FilterListener,
        ViewTreeObserver.OnTouchModeChangeListener,
        RemoteViewsAdapter.RemoteAdapterConnectionCallback {

    class AdapterDataSetObserver extends AdapterView<ListAdapter>.AdapterDataSetObserver {
        @Override
        public void onChanged() {
            super.onChanged();
            if (mFastScroll != null) {
                mFastScroll.onSectionsChanged();
            }
        }

        @Override
        public void onInvalidated() {
            super.onInvalidated();
            if (mFastScroll != null) {
                mFastScroll.onSectionsChanged();
            }
        }
    }
            
}

  这个又继承自AbsListView的父类AdapterView的AdapterDataSetObserver,具体代码如下:

public abstract class AdapterView<T extends Adapter> extends ViewGroup {
    
    class AdapterDataSetObserver extends DataSetObserver {

        private Parcelable mInstanceState = null;
        //前面说的调用Adapter的notifyDataSetChanged()时会调用所有观察者的onChanged()方法,核心实现就是这里;
        @Override
        public void onChanged() {
            mDataChanged = true;
            mOldItemCount = mItemCount;
            //获取Adapter中的数据的数量;
            mItemCount = getAdapter().getCount();
            if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
                    && mOldItemCount == 0 && mItemCount > 0) {
                AdapterView.this.onRestoreInstanceState(mInstanceState);
                mInstanceState = null;
            } else {
                rememberSyncState();
            }
            checkFocus();
            //重新布局ListView、GridView等AdapterView组件;
            requestLayout();
        }

        @Override
        public void onInvalidated() {
            mDataChanged = true;
            if (AdapterView.this.getAdapter().hasStableIds()) {
                mInstanceState = AdapterView.this.onSaveInstanceState();
            }
            mOldItemCount = mItemCount;
            mItemCount = 0;
            mSelectedPosition = INVALID_POSITION;
            mSelectedRowId = INVALID_ROW_ID;
            mNextSelectedPosition = INVALID_POSITION;
            mNextSelectedRowId = INVALID_ROW_ID;
            mNeedSync = false;
            checkFocus();
            requestLayout();
        }

        public void clearSavedState() {
            mInstanceState = null;
        }
    }
    
}

  到这里就会知道,当ListView的数据发生变化时,调用Adapter的notifyDataSetChanged()方法,会调用DataSetObservable的notifyChanged()方法,又会调用所有观察者(AdapterDataSetObserver)的onChanged()方法,在onChanged()方法中又会调用ListView重新布局的方法使得ListView刷新界面,这就是一个观察者模式。
  AdapterView中有一个内部类AdaperDataSetObserver,在ListView中设置Adapter时会构建一个AdapterDataSetObserver,并且注册到Adapter中,这就是一个观察者。而Adapter中包含一个数据集可观察者DataSetObservable,在数据数量发生变更时,开发者手动调用Adapter.notifyDataSetChanged(),而Adapter.notifyDataSetChanged()实际上调用DataSetObserver的notifyChanged()方法,该方法会遍历所有观察者的onChanged()方法。在AdapterDataSetObserver的onChanged()方法中会获取Adapter中数据集的新数量,然后调用ListView的requestLayout()方法重新进行布局,更新用户界面。

-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
----------------------last line for now----------------------