registerDataSetObserver:浅析Andorid ListView和Adapte
最近由于遇到将内容分部绑定到ListView里的需求,追踪源码之后对ListView和Adapter有了点肤浅的认识,在此与大家分享。
这里用到了观察者模式,在ListView的setAdapter里注册一个AdapterDataSetObserver观察者。
- public void setAdapter(ListAdapter adapter) {
- ........
- mDataSetObserver = new AdapterDataSetObserver();//AdapterDataSetObserver是ListView的基类AdapterView的内部类
- mAdapter.registerDataSetObserver(mDataSetObserver);//注册一个观察者
- .........
- requestLayout();//更新视图
- }
ListAdapter是一接口,BaseAdapter继承了它
- public abstract class BaseAdapter implements ListAdapter, SpinnerAdapter {
- private final DataSetObservable mDataSetObservable = new DataSetObservable();
- public boolean hasStableIds() {
- return false;
- }
- public void registerDataSetObserver(DataSetObserver observer) {
- mDataSetObservable.registerObserver(observer);
- }
- public void unregisterDataSetObserver(DataSetObserver observer) {
- mDataSetObservable.unregisterObserver(observer);
- }
- /**
- * 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();
- }
- /**
- * Notifies the attached observers that the underlying data is no longer valid
- * or available. Once invoked this adapter is no longer valid and should
- * not report further data set changes.
- */
- public void notifyDataSetInvalidated() {
- mDataSetObservable.notifyInvalidated();
- }
- public boolean areAllItemsEnabled() {
- return true;
- }
- public boolean isEnabled(int position) {
- return true;
- }
- public View getDropDownView(int position, View convertView, ViewGroup parent) {
- return getView(position, convertView, parent);
- }
- public int getItemViewType(int position) {
- return 0;
- }
- public int getViewTypeCount() {
- return 1;
- }
- public boolean isEmpty() {
- return getCount() == 0;
- }
- }
DataSetObservable定义如下:
- public class DataSetObservable extends Observable<DataSetObserver> {
- public void notifyChanged() {//通知每个观察者数据已变化
- synchronized(mObservers) {
- for (DataSetObserver observer : mObservers) {
- observer.onChanged();
- }
- }
- }
- public void notifyInvalidated() {
- synchronized (mObservers) {
- for (DataSetObserver observer : mObservers) {
- observer.onInvalidated();
- }
- }
- }
- }
ListView里注册的观察者是AdapterDataSetObserver对象,其定义如下:
- class AdapterDataSetObserver extends DataSetObserver {
- private Parcelable mInstanceState = null;
- @Override
- public void onChanged() {
- mDataChanged = true;
- mOldItemCount = mItemCount;
- mItemCount = getAdapter().getCount();//Adapter现有元素个数
- if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
- && mOldItemCount == 0 && mItemCount > 0) {
- AdapterView.this.onRestoreInstanceState(mInstanceState);
- mInstanceState = null;
- } else {
- rememberSyncState();
- }
- checkFocus();
- requestLayout();//更新视图
- }
- .................
- }
AdapterDataSetObserver里的具体实现我没弄清楚,但感觉是在这里更新了ListView显示的数据,ListView里是怎样更新的没弄清楚,希望哪位高手知道的告诉我。
但是如果只在ListView里显示Adapter的部分数据,该怎么弄呢,可继承BaseAdapter,实现BaseAdapter里未实现的如下方法:
getCount()、getItem(int position)、getItemId(int position)、getView(int position, View convertView, ViewGroup parent)。
只需在getCount里返回想要的大小就行了。
我思故我在