天天看点

从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么

导师安排我做一个小项目,其中涉及到利用adapter作为listview的适配器,为listview提供数据。选中某一项后,要让这一项变成选中状态,也就是背景图片要换一下。下面我就用一个小例子来模拟。重点不在于实现,而是了解adapter中notifydatasetchanged()背后的运行机制。

    我们先做一个小demo(文中涉及的demo在文章末尾),功能是选中某一项后,背景颜色会变红。代码非常简单,这里就不解释了。值得注意的是,当我们需要listview进行刷新的时候,我们需要调用adapter.notifydatasetchanged()来让界面刷新。

从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么
从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么

适配器myarrayadapter代码:

从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么
从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么

下面就让我们跟进去myarrayadapter.notifydatasetchange()中看看。在本文中,我所查看的android源代码是4.4.0的,不同版本可能有所出入。

源代码就简单两句话,那么继续看看super是什么?

从类的声明中,父类就是arrayadapter,而arraylist的父类是baseadapter。我们跟进baseadapter中看看。

从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么
从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么

我们发现其实就是datasetobservable这个对象在发生作用,但是datasetobservable这个对象估计就是一个简单的观察者的实现,android框架的编写者不大可能将业务逻辑放在这里面,不过我们还是要确认是不是跟我们所想的一样。

从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么
从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么

果然,跟预想的一样,它只是简单地调用了绑定在它身上的回调接口。那么baseadapter.notifydatasetchange()的接口具体是在哪里绑定的呢?很有可能在构造函数中绑定,我们跟进arraylistadapter看看。

从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么
从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么

arraylistadapter中有很多构造函数,但是几经辗转全部都会转到init()函数中,很遗憾,我们扑空了。那么还在哪里可能绑定notifydatasetchange()回调函数呢?其实从mainactivity中adapter的初始化过程中,基本上只能锁定在mainactivity第十行中setadapter函数中。接下去看看 public void setadapter(listadapter adapter)这个函数。 

从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么
从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么

setadapter(...)这个函数有点长,不过我们只需要关注跟notifidatasetchange()有关的实现,也就是第23、24行。不过这里另一个值得关注的点就是第63行,requestlayout()这个函数,它主要就是用来刷新界面,让界面重新绘制的。在23,、24行,绑定了一个adapterdatasetobserver对象,下面我们就跟进去看看。从前面datasetobservable的实现中,我们知道了它在notifydatasetchange()的时候会调用datasetobserver的onchange()。

从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么
从源代码的角度分析--在BaseAdapter调用notifyDataSetChanged()之后发生了什么

终于,在第19行,我们看见了requestlayout(),它就是用来重绘界面的,它在viewrootimpl.java中有具体的实现。

    到了这里,我们就清楚了notifydatasetchange()背后的实现机制了,在不知不觉之间android框架帮我们干了很多事情,不过需要提醒的时,每一次notifydatasetchange()都会引起界面的重绘。当需要修改界面上view的相关属性的时候,最后先设置完成再调用notifydatasetchange()来重绘界面。

本文版权归作者所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

转载:http://www.cnblogs.com/kissazi2/p/3721941.html

继续阅读