您的位置:首页 > 其它

连接AdapterView视图和数据源的桥梁:Adapter适配器(3)

2016-03-08 00:57 274 查看
BaseAdapter是一种使用频率较高的适配器,因为它可以通过自定义最大程度扩展满足各种情景下的使用。我们不仅需要知道适配器的使用,进一步我们也需要了解适配器的原理。

问题是最好的学习方式,下面主要讨论这么几个问题:

Q1.ListView中每个Item的创建

Q2.ListView中Item的复用

Q3.ListView中屏幕显示的Item与复用生成Item之间的关系

  首先写一个简单的demo.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp">

<ImageView
android:id="@+id/item_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"
android:padding="4dp"/>

<TextView
android:id="@+id/item_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:textStyle="bold"
android:layout_toRightOf="@id/item_icon"
android:layout_alignTop="@id/item_icon"/>
<TextView
android:id="@+id/item_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="16sp"
android:layout_below="@id/item_title"
android:layout_toRightOf="@id/item_icon"
android:layout_alignBottom="@id/item_icon"/>

<TextView
android:id="@+id/item_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/item_title"
android:layout_alignParentRight="true"
android:gravity="right"/>
<CheckBox
android:id="@+id/item_check"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@null"
android:layout_below="@id/item_date"
android:layout_alignParentRight="true"
android:gravity="center"
android:layout_alignBottom="@id/item_content"/>
</RelativeLayout>


item.xml
由于该Demo比较简单,不需多讲相信都可以看懂。

ItemBeanAdapter.java的getView方法中有这么一句:

  


 分别打印的是ListView中每一个Item在ListView中的位置(默认从0开始,下同),该Item显示的数据源中指定位置数据的poistion和title,convertView是否为空若不为空打印convertView之前显示的title.

 当数据源中的数据条数为5时,Logcat的日志:

  


  UI:

  


 当数据源中的数据条数为10是,Logcat的日志:

  


  UI:

  


  

  根据这两种情况的测试,可以大概回答第一个问题:

Q1.ListView中每个Item的创建

A1.Adapter第一次创建的Items的数量是由手机屏幕的大小(可测试)和数据源数据的条数来决定的,也就是屏幕实际显示多少个Item就创建几个item的,不多创建新的item也不少创建新的item,items数量是屏幕实际显示数目的取整。将下面的完整结合来看,第一次创建的Item是最基本的Item,它的数量是确定的,以后新的item无论是向上滑动出现还是向下滑动出现都是复用第一次创建的items中的某个item。

Q2.ListView中Item的复用

A2:最核心的代码就是Adapter中的getView方法,它返回的是一个已经绑定好数据的view,而系统仅仅只是将这个view在屏幕的指定位置绘制出来。

  


  代码不是固定死的,当然你可以有自己的写法,但是原理总是相同的:

    A2:当ListView第一次创建一屏幕的items时,covertView始终为null(代码测试很容易得出),所以当covertView为空时,就需要将第一次创建一屏幕的items的每个item“初始化”,这里的“初始化”是将covertView和ViewHolder绑定起来,注意不论是将covertView和ViewHolder绑定起来还是ret和ViewHolder绑定起来,它们的本质是一样的,最后返回值是已经与ViewHolder绑定的View视图,当掌握了covertView的复用写法,可以说是基本上item的复用的写法也掌握了。

    注意下面一种情况,当ListView向上滑动,且item0完全不见,item7和item8出现(下图item8已经出现,只是没有完全显示)的情况:

    


    此时Logcat打印的日志:

    

  

    根据之前的第一次创建items打印的日志比较:item7仍然是新创建的,但是item8却是复用的,item8复用的是item0(完全根据日志得出的)。(PS 可能此处有疑问,下面会分析)

    A2:当listView向上滑动或者是向下滑动的时候,此时可能会出现item复用的情况(注意此时可能会出现复用的情况,不一定或出现哦)。若covertView不为空,就可以之前在该covertView初始化或复用中通过getTag方法,取出与之绑定的ViewHolder,从而实现减少findViewById的时间,findViewById是需要耗费时间的,当listView显示大量的数据,此时的findViewByid可以极大的提高效率。

    最后分析总结前面的,可以回答第三个问题:

Q3.ListView中屏幕显示的Item与复用生成Item之间的关系

A3:ListView实际创建item的数量是由手机屏幕的大小和数据源的数据数量来决定的,准确的将这是不准确的或是错误的。

  ListView在整个复用过程中本质上实际创建item的数量(这里所指的全部是最原始最本质的item)是由手机屏幕的大小、数据源的数据数量和每个item实际的大小来决定的(当然这里不考虑其他更为负责的情况,而是假定每个item的大小相同)。

   用可以唯一衡量确定的话说是:本质上items的数量是当第一个item完全消失后,此时Adapter总共创建的items数量,从本质上来说,这就是ListView在整个复用过程中复用的item的数量。假如从0,1,...,n-1(n为最原始的item数量)来看,当ListView向上滑动时,复用tem的顺序是按顺序复用0,1,...,n-1,每次复用一个;当ListView向下滑动时,复用的顺序是按照逆序的,从n-1,n-2,..,0,也是一个一个复用的。

  当然还有更为复杂的情况或者说从更为本质也就是源码的角度分析,这里暂不考虑,而是从一种最为表象或者最最最基本最最简单来分析ListView与Adapter。

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: