• 转:ListView中getView的工作原理


    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的事情,也节省了很多资源避免去重复做无用功。
    谢谢!

  • 相关阅读:
    智能制造及其十大关键技术
    浅谈华为验厂对MES系统的要求
    aps系统切换切记“三要三不要”
    周黑鸭借力MES,推进智能生产
    MES助力伊利集团打造智慧工厂
    智能制造下一个风口:工业智能
    大规模定制模式之于MES的三点思考
    APS中生产计划排程模块的基本原理
    通读审计之wiinews
    wiinews sql注入漏洞分析
  • 原文地址:https://www.cnblogs.com/1995hxt/p/5795399.html
Copyright © 2020-2023  润新知