分享解析baseAdapter源代码

    今天初七,羊年工作的第一天,这里f给大家拜个晚年。最近在做项目时候,根据需要涉及到了baseAdapter的一些用法,众所周知,adapter很好的运用了观察者模式,f看<head first>时候,看了这个模式,demo也敲过,但是对真正的应用没有源代码级别的接触,于是找时间研究了baseAdapter的源码,跟大家分享一下。

    baseAdapter作为一个抽象类,实现了listAdapter以及spinnerAdapter接口,它俩又同样继承了adapter接口。adapter接口中有一些抽象方法10个

    listAdapter新增加了方法2个

spinnerAdapter新增加了方法1个

而baseAdapter实现了


    乍一看有些乱,我来捋捋

baseAdapter其实间接,直接的实现了三个adapter里的方法,listAdapter,spinnerAdapter并未实现adapter的方法,而是新增了方法


registerDataSetObserver(DataSetObserver observer);

unregisterDataSetObserver(DataSetObserver observer);

adapter的这两个方法是用来注册 注销观察者的。

这两个方法在baseAdapter里已经实现

int getCount();
 Object getItem(int position);

long getItemId(int position);

 View getView(int position, View convertView, ViewGroup parent);

adapter的这四个方法没有被实现,所以我们在自定义adapter继承baseAdapter时候,也就要重写这四个方法

adapter的boolean hasStableIds();在baseAdapter里实现,返回值是false

这个方法的意思是表达每个item的id对于数据集的改变是否是稳定不变的,如果返回true,表示每个object的id都一样,

如果都一样,我们修改时候,在内存中指向的便是同一块地址,这不合逻辑,所以在baseAdapter里返回false,即

每个object都有不一样的id。

 int getItemViewType(int position);

int getViewTypeCount();

这两个方法分别表示通过特定item创建的view的类型和对应的编号

 boolean isEmpty();

这个方法表示是否adapter包含数据

listAdapter中两个抽象方法分别表示,adapter里的所有item或者指定位置的item是否是enabled,我们遇到相关需求时候,

可以重写这些方法,实现不同的目的

baseAdapter重写spinnerAdapter时候,在重写的方法里调用了View getView(int position, View convertView, ViewGroup parent);


adapter观察者模式的体现,就是register这个方法,方法中执行了观察者对象的注册

public void registerDataSetObserver(DataSetObserver observer) {
        mDataSetObservable.registerObserver(observer);
    }

BaseAdapter每次新建时候,都会创建一个类似主题的对象

private final DataSetObservable mDataSetObservable = new DataSetObservable();


这里还会有点乱。。。

DataSetObservable是Observable<DataSetObserver>的实现类,且看registerObserver方法

protected final ArrayList<T> mObservers = new ArrayList<T>();


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


在Android里 DataSetObservable,DataSetObserver作为观察者模式的主题和观察者对象,已经被绑定在一起

在baseAdapter的重写的方法中已经把两个对象作为参数传入。



什么是adapter呢?按文档解释,adapter是adapterview和对应的view的数据集之间的桥梁,其实就是为了显示数据在listview等显示而创造的

adapter对于观察者模式的运用最明显的是adapter的notifyDataSetChanged方法,

public void notifyDataSetChanged() {
        mDataSetObservable.notifyChanged();
    }

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

看到这以后,f又习惯性地去找onchanged方法,才发现这个方法是个抽象方法,然后就傻了,大家都知道,调用adapter的notifyDataSetChanged

方法后,界面会重新绘制,但是按照目前的逻辑是不会出现画界面的结果的。。。怎么解决呢?对对,那就是debug,看代码是怎么运行的

在前面其实埋了一个坑,为何重写的方法里有注册有注销,但是是怎么调用的呢?还记得baseAdapter怎么用吗?

要新建,然后调用listview 的setAdapter,这个方法,是个及其重要的方法。

这里对adapter以及观察者对象做了判断,刚开始adapter不为空,观察者对象为空,程序不执行注销的方法,而是往下运行,

下面,执行了观察者对象的注册, mDataSetObserver = new AdapterDataSetObserver();
            mAdapter.registerDataSetObserver(mDataSetObserver);

所以在调用notifyDataSetChanged方法时,是有一个观察者对象存在。

debug到此,进入方法一看,是执行这一步,

传递的Index是0,应该不会报数组下标越界的错

然后又继续执行重写的方法。执行完后回到

再次进入后执行

然后数据集包括与之关联的view都会被移入堆内存等待循环回收。

好乱的感脚。。。

都是f自己debug很多次得到的结论,adapter块的源码确实复杂。

不知道分析是否有错误,目前f严重处于初级阶段,还请大家多多跟f交流,彼此提高技术水平,f也会抽时间找一些有意义的内容和大家共享!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值