关闭

ListView BaseAdapter中的观察者模式

1750人阅读 评论(1) 收藏 举报
分类:

Android SDK源码中用到了很多开发模式,其中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);
    }

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

public abstract class Observable<T> {
    /**
     * The list of observers.  An observer can be in the list at most
     * once and will never be null.
     */
    protected final ArrayList<T> mObservers = new ArrayList<T>();

    /**
     * Adds an observer to the list. The observer cannot be null and it must not already
     * be registered.
     * @param observer the observer to register
     * @throws IllegalArgumentException the observer is null
     * @throws IllegalStateException the observer is already registered
     */
    public void registerObserver(T observer) {
        if (observer == null) {
            throw new IllegalArgumentException("The observer is null.");
        }
        synchronized(mObservers) {
            if (mObservers.contains(observer)) {
                throw new IllegalStateException("Observer " + observer + " is already registered.");
            }
            mObservers.add(observer);
        }
    }

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

被观察者对象调用方法

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

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

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

 @Override
    public void setAdapter(ListAdapter adapter) {
        if (mAdapter != null && mDataSetObserver != null) {
            mAdapter.unregisterDataSetObserver(mDataSetObserver);
        }

        resetList();
        mRecycler.clear();

        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
            mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
        } else {
            mAdapter = adapter;
        }

        mOldSelectedPosition = INVALID_POSITION;
        mOldSelectedRowId = INVALID_ROW_ID;

        // AbsListView#setAdapter will update choice mode states.
        super.setAdapter(adapter);

        if (mAdapter != null) {
            mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
            mOldItemCount = mItemCount;
            mItemCount = mAdapter.getCount();
            checkFocus();

            mDataSetObserver = new AdapterDataSetObserver();
            mAdapter.registerDataSetObserver(mDataSetObserver);

            mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());

            int position;
            if (mStackFromBottom) {
                position = lookForSelectablePosition(mItemCount - 1, false);
            } else {
                position = lookForSelectablePosition(0, true);
            }
            setSelectedPositionInt(position);
            setNextSelectedPositionInt(position);

            if (mItemCount == 0) {
                // Nothing selected
                checkSelectionChanged();
            }
        } else {
            mAreAllItemsSelectable = true;
            checkFocus();
            // Nothing selected
            checkSelectionChanged();
        }

        requestLayout();
    }

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

 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();
            }
        }
    }

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


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

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


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












1
1
查看评论

ListView之BaseAdapter的用法简单案例(四)

一个简单的BaseAdapter的用法简单案例, 我们想利用BaseAdapter达到下面图片的简单效果。 首先我们先将布局文件写出来如下<?xml version="1.0" encoding="utf-8"?> <LinearLayo...
  • qq_34487977
  • qq_34487977
  • 2016-04-07 18:34
  • 1745

Android入门:ListView(继承BaseAdapter实现)

任务: 从数据库中获得Person对象,通过继承BaseAdapter类,显示ListView,如下所示: (此处我们数据库操作的代码略,因为主要讲解的是ListView) PersonAdapter.java package org.xiazdong.db.do...
  • xiazdong
  • xiazdong
  • 2012-07-01 08:15
  • 13376

Fragment 与 ListView, BaseAdapter

转自:http://blog.csdn.net/guolin_blog/article/details/8881711 Fragment初探 为了让界面可以在平板上更好地展示,Android在3.0版本引入了Fragment(碎片)功能,它非常类似于Activity,可以像Activity...
  • xilove102
  • xilove102
  • 2015-09-23 10:36
  • 4223

一个基于BaseAdapter适配ListView的完整示例

改写郭霖老师的《第一行代码》里面的一个关于水果的小例子,基于BaseAdapter适配ListView的完整示例
  • jinxin_cuit
  • jinxin_cuit
  • 2016-09-08 08:47
  • 1485

Android-ListView适配器BaseAdapter的使用和优化

Android-ListView适配器BaseAdapter的使用 这是BaseAdapter的相应的方法属性。 像SimpleAdapter和ArrayAdapter都是继承于BaseAdapter。 可以查看其源码: SimoleAdapter ArrayAdapter 写几...
  • ACM_TH
  • ACM_TH
  • 2016-04-12 09:57
  • 3921

ListView中getChildAt()方法以及BaseAdapter中getview使用

一、概述 在项目开发过程中,需要动态更新标题栏上下拉框中listview的每个item,要求是有未读信息时,添加一个红点标识。 这里主要使用CircleBadgeView这个控件,主要是想在不改变listview中item布局的情况下实现给每个item右边添加红点的效果。 二,动态更新红点标识...
  • u010727953
  • u010727953
  • 2016-07-04 11:44
  • 610

listview的简单使用(Baseadapter)

本篇主要是写下listview的简单实现。(使用Baseadapter) 在自己理解之后稍微做下笔记,在Baseadapter的部分增添了较多注释。 也是希望能给和我一样的新手们一些帮助。   以下是实现效果:     ...
  • Double2hao
  • Double2hao
  • 2015-07-21 12:21
  • 2228

android组件ListView之BaseAdapter简单使用

前面所说的arrayAdapter和SimpleAdapter都是在BaseAdapter基础之上为我们封装好了功能,但是只能在特定情况下使用,不够灵活。今天我们动手写一个自己的Adapter。继承与BaseAdapter,实现四个抽象方法。分别是 getCount() 、getItem(int i...
  • sinat_25926481
  • sinat_25926481
  • 2017-04-27 21:03
  • 1687

Android复习练习十一(ListView列表显示使用BaseAdapter以及ListView动态刷新)

需求:结合SQLite数据库,实现一个取
  • cyp331203
  • cyp331203
  • 2014-09-04 18:20
  • 1440

ListView的优化和自定义适配器继承于BaseAdapter

ListView的优化和万能适配器继承于BaseAdapter          在android开发中Listview是一个很重要的组件,它以列表的形式根据数据的长自适应展示具体内容,用户可以自由的定义listview每一列的布局,但当listv...
  • u013128651
  • u013128651
  • 2016-03-21 20:14
  • 2805
    个人资料
    • 访问:2611278次
    • 积分:16277
    • 等级:
    • 排名:第762名
    • 原创:179篇
    • 转载:140篇
    • 译文:4篇
    • 评论:383条
    最新评论