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----------------------