ListView中getView的工作原理:

[1]ListView asks adapter “give me a view” (getView) for each item of the list.(通过getView来获取每个item)

[2]A new View is returned and displayed(获取到后返回显示)

那么如果我们有大量的数据需要显示的时候,每个Item都去重复执行getView中的创建新的View的动作吗?这样做会耗费大量的资源去执行重复的事情,实际上Android为我们提供了一套重复利用的机制叫做原理简单描述下就是这样:

在 一个完整的ListView第一次出现时,每个Item都是Null的,getView的时候会跑到需要inflate一个Item的代码段,假设整个 view只能最多显示10个item,那么当滑动到第11个Item的时候,第一个item会放入“recycler”,如果第11个Item和放入 “Recycler”的item的view一致,那么就会使用"Recycler"里面的Item来显示,从而不用再重复inflate一次,这样大大节 省了创建View的工作,在需要显示大量数据时显得尤为重要。

工作原理的示意图如下:


学习自http://android.amberfog.com/?p=296

Demo:

这是一个getView的方法,其他细节的Code就不显示了

  1. staticclass

    publicnull
    publicnull
    publicnull
    publicnull

    publicint

    ifnull

    null
    ifnull

    this"convertView == null,Then inflate and findViewById"
    thisfalse
    new

    else

  2. this"convertView != null,Then findViewById(get Holder)"

    ifnull

    this"convertView != null,Then SetValue"

    int
    +id++mstr);

  3. +name);
  4. +url);
  5. return
        }




当我们第一次启动到Listview的时候如下,只显示了5个Item,那么getView被调用5次:


打印的Log如下:可以看到从0-4都是null,我们需要做inflate的动作,

  1. </strong>



当我们小心往下滑动一个位置,刚出现第6个Item,此时第1个还没有消失时,


这个时候只打印了一个获取第6个Item的Log,如下:可以看到第6个Item还是为null,需要inflate出来新的

  1. </strong>



如果此时再往下滑动列表,第1个item此时会放入Recycler,第7个Item此时不再是null,而是利用了第1个item的View,如下:


从下面的Log,可以看到从第7个开始就不是null了

01-12 18:52:36.243: ERROR/MusicDemo(1272): @kesen@ [ main: Activity4Adapter.Java:69 getView ] - This is position:6

01-12 18:52:36.243: DEBUG/MusicDemo(1272): @kesen@ [ main:
Activity4Adapter.java:89 getView ] - convertView != null,Then
findViewById
01-12 18:52:36.243: DEBUG/MusicDemo(1272): @kesen@ [ main:
Activity4Adapter.java:98 getView ] - convertView != null,Then SetValue
01-12 18:52:36.693: ERROR/MusicDemo(1272): @kesen@ [ main: Activity4Adapter.java:69 getView ] - This is position:7
01-12 18:52:36.693: DEBUG/MusicDemo(1272): @kesen@ [ main:
Activity4Adapter.java:89 getView ] - convertView != null,Then
findViewById
01-12 18:52:36.693: DEBUG/MusicDemo(1272): @kesen@ [ main:
Activity4Adapter.java:98 getView ] - convertView != null,Then SetValue
01-12 18:52:37.024: ERROR/MusicDemo(1272): @kesen@ [ main: Activity4Adapter.java:69 getView ] - This is position:8
01-12 18:52:37.024: DEBUG/MusicDemo(1272): @kesen@ [ main:
Activity4Adapter.java:89 getView ] - convertView != null,Then
findViewById
01-12 18:52:37.034: DEBUG/MusicDemo(1272): @kesen@ [ main:
Activity4Adapter.java:98 getView ] - convertView != null,Then SetValue
01-12 18:52:37.604: ERROR/MusicDemo(1272): @kesen@ [ main: Activity4Adapter.java:69 getView ] - This is position:9
01-12 18:52:37.604: DEBUG/MusicDemo(1272): @kesen@ [ main:
Activity4Adapter.java:89 getView ] - convertView != null,Then
findViewById
01-12 18:52:37.604: DEBUG/MusicDemo(1272): @kesen@ [ main:
Activity4Adapter.java:98 getView ] - convertView != null,Then SetValue

等所有的item,一共10个都显示之后,不管上下滑动都再也不是NULL了,说明这个时候都是使用Recycle里面的view,而不会再重新inflate了,显然这样节省很多重复的操作

【1】重复多轮调用getView的解决方案

上面的例子我们可以看到,每滑动一次到需要显示的Item的时候就会调用一次
getView,理论上是10个Item,均显示一次的话是要调用getView()
10次的,那么为什么有时候很奇怪,10个item显示一次也许会调用getView 20次,甚至40-50次呢?我想肯定很多人都遇到过这个问题

查了很久,其实我也没有找到root cause,只是知道我们在XML文件里面定义listView的时候需要设置height为fill_parent或者是指定的高度值(这个方法明显不靠谱,设置了高度,那么怎么进行不同屏幕的适配)

所以推荐使用下面的,例如:

<ListView android:id="@+id/activity04_list" android:layout_width="fill_parent" android:layout_height="fill_parent"/>

网上有人解释说是因为ListView的Item的高度计算方法问题,试了下还是有效果的,希望之后有机会等了解原理后再来解释这个问题,我们可以先这也
使用,设置之后会发现没滑动出现一个item才会调用一次getView,这样是合理的调用,而不会出现只有10个item却调用几十次这样比较
tricky的事情,也节省了很多资源避免去重复做无用功。
谢谢!

转:ListView中getView的工作原理的更多相关文章

  1. [转][Android] ListView中getView的原理+如何在ListView中放置多个item

      ListView 和 Adapter 的基础 工作原理: ListView 针对List中每个item,要求 adapter “给我一个视图” (getView). 一个新的视图被返回并显示 如果 ...

  2. Android 中View的工作原理

    Android中的View在Android的知识体系中扮演着重要的角色.简单来说,View就是Android在视觉的体现.我们所展现的页面就是Android提供的GUI库中控件的组合.但是当要求不能满 ...

  3. Java中GC的工作原理

    转文: 一个优秀的Java程序员必须了解GC的工作原理.如何优化GC的性能.如何与GC进行有限的交互,有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只有全面提升内存的管理效率,才能提高整个 ...

  4. 梳理源码中 View 的工作原理

    欢迎Follow我的GitHub, 关注我的掘金. 在View的工作过程中, 执行三大流程完成显示, 测量(measure)流程, 布局(layout)流程, 绘制(draw)流程. 从perform ...

  5. JavaScript中this的工作原理以及注意事项

    在JavaScript中,this 的概念比较复杂.除了在面向对象编程中,this 还是随处可用的.这篇文章介绍了this 的工作原理,它会造成什么样的问题以及this 的相关例子. 要根据this  ...

  6. android ListView 中getview学习总结

    最近在做android相关的开发,ListView中有一个图片错位的问题,今天查了很多人写的一些东西,所以记录下来,算是一种加深理解吧. ListView是一个非常常用的控件,功能可以扩展的很丰富,而 ...

  7. Tomcat中JSP引擎工作原理

    http://blog.csdn.net/linjiaxingqqqq/article/details/7164449 JSP运行环境: 执行JSP代码需要在服务器上安装JSP引擎,比较常见的引擎有W ...

  8. java中jvm的工作原理

    首先我们安装了jdk和jre,但是jdk是为java软件开发工程师而使用的开发工具,我们运行java项目只要含有jre文件即可.对于jvm是内存分配的一块区域,我们知道,当我们开始使用java命令时, ...

  9. Ceph对象存储网关中的索引工作原理<转>

    Ceph 对象存储网关允许你通过 Swift 及 S3 API 访问 Ceph .它将这些 API 请求转化为 librados 请求.Librados 是一个非常出色的对象存储(库)但是它无法高效的 ...

随机推荐

  1. linux下载利器之curl和wget的区别

    linux下载利器-------curl和wget的区别 curl和wget基础功能有诸多重叠,如下载等. 在高级用途上的curl由于可自定义各种请求参数所以长于模拟web请求,用于测试网页交互(浏览 ...

  2. thinkphp5 获取器的

    获取器的作用是在获取数据的字段值后自动进行处理,例如,我们需要对状态值进行转换,可以使用: 1.数据库字段转换. class User extends Model { public function ...

  3. 【Effective C++ 读书笔记】条款04:确定对象使用前已先被初始化

    永远在使用对象之前先将它初始化.对于无任何成员的内置类型,你必须手工完成此事. 至于内置类型以外的任何其他东西,初始化责任落在构造函数身上.规则很简单:确保每一个构造函数都将对象的每一个成员初始化. ...

  4. 右键git-bash不能使用

    主要:右键git-bash不能使用 右键git-bash不能使用 今日想用git传写代码到仓库,突然发现几天没有却出问题了,右键出现了错误,虽然很快解决了,但还是可以记录下 情形: 右键存在但不能使用 ...

  5. php COM

    查看php.ini中是否已经开启了com.allow_dcom = true 从php/ext/里面查找一下有没有这个php_com_dotnet.dll这个文件 如果没有网上下载个,一般都会有的吧应 ...

  6. GMT 时间格式转换到 TDateTime (Delphi)

    //GMT 时间格式转换到 TDateTime //忽略时区 function GMT2DateTime(const pSour:PAnsiChar):TDateTime; function GetM ...

  7. C语言进阶——类型转换04

    C语言内可以进行类型转换: 强制类型转换 隐式类型转换 强制类型转换的语法: (tpye)value (type)value_name 强制类型转换的结果: 目标类型可以容纳目标值:结果不变 目标值不 ...

  8. [BZOJ3631][JLOI2014]松鼠的新家(树链剖分)

    [BZOJ3631] 树剖模板题了, Code #include <cstdio> #include <algorithm> #define MID int mid=(l+r) ...

  9. Snowflake Snow Snowflakes【Poj3349】

    Description You may have heard that no two snowflakes are alike. Your task is to write a program to ...

  10. IIS发布错误记录

    1.HTTP 错误 500.19 - Internal Server Error 无法访问请求的页面,因为该页的相关配置数据无效. 详细错误信息模块 IIS Web Core 通知 BeginRequ ...