zoukankan      html  css  js  c++  java
  • BaseAdapter中重写getview的心得以及发现convertView回收的机制

    http://blog.csdn.net/pkxiuluo01/article/details/7380974

    以前一直在用BaseAdapter,对于其中的getview方法的重写一直不太清楚。今天终于得以有空来探究它的详细机制。
    下面先讲讲我遇到的几个问题:
    一.View getview(int position, View convertview, ViewGroup parent )中的第二个参数是什么含义;
    二.View的SetTag和getTag方法的用途;
    先来解决第一个问题:
    android SDK中这样讲参数 convertview :
    the old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using.

     If it is not possible to convert this view to display the correct data, this method can create a new view.
    翻译:
    如果可以的话,这是旧View(这里不便翻译有的人翻成视图)的重用。 建议:在用之前,你应该检查这个View是
    不是非空,是不是一个合适的类型。
    如果不可能让这个VIew去显示一个恰当的数据,这个方法会创建一个新的View。

    如果我们要做的是一个ListView,在手机上显示的只有那么几条Item,而整个ListView可能有很长,可能是100条
    甚至是上万条,总不能让这么多条Item都驻留在内存中,所以android为你准备了一套机制,就是Recycler(反复循
    环器),他的具体工作原理可以到 http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html去看。
    但是有些地方他没有讲清,所以我再讲一下。先把代码贴出来
    布局文件main.xml


    1. <?xml version="1.0" encoding="utf-8"?>  
    2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    3.     android:layout_width="fill_parent"  
    4.     android:layout_height="fill_parent"  
    5.     android:orientation="vertical" >  
    6.     <ListView  
    7.         android:id="@+id/result"  
    8.         android:layout_width="fill_parent"  
    9.         android:layout_height="fill_parent"  
    10.         android:cacheColorHint="#00000000" >  
    11. </ListView>  
    12. </LinearLayout>  

    此处注意ListView的android:layout_height属性值为"fill_paternt",如果为“wrap_content"将会是另一种情况

    adapter的代码ListViewAdapter.java 

    1. class ListViewAdapter extends BaseAdapter  
    2.    {  
    3.         private Context mContext;  
    4.         int i=0;  
    5.         public ListViewAdapter (Context context)  
    6.         {  
    7.             this.mContext=context;  
    8.         }  
    9.     @Override  
    10.     public int getCount()  
    11.     {  
    12.         return 30;  
    13.               
    14.     }  
    15.     @Override  
    16.     public Object getItem(int position)  
    17.     {  
    18.                 return position;  
    19.     }  
    20.     @Override  
    21.     public long getItemId(int position)  
    22.     {  
    23.                 return 0;  
    24.     }  
    25.     @Override  
    26.     public View getView(int position, View convertView, ViewGroup parent)  
    27.     {  
    28.          System.out.println("getView " + position + " " + convertView);//调试语句  
    29.          Holder holder;  
    30.         if(null==convertView)  
    31.         {  
    32.             holder=new Holder();  
    33.             convertView=LayoutInflater.from(mContext).inflate(R.layout.textview, null); //mContext指的是调用的Activtty  
    34.             holder.textView=(TextView)convertView.findViewById(R.id.textview);  
    35.             convertView.setTag(holder);  
    36.         }  
    37.         else  
    38.         {  
    39.             holder=(Holder)convertView.getTag();  
    40.         }  
    41.         holder.textView.setText("position: "+position);  
    42.             return convertView;           
    43.     }  
    44.     class Holder  
    45.     {  
    46.         public TextView textView;  
    47.   
    48.     }  
    49.     }  

    运行程序之后发现屏幕上显示出的Item的convertview都为空,向下滑动新产生的Item的convetview都不为空。到此为止和上面链接中讲的是一致的,但是如果设置ListView的android:layout_height属性值为“wrap_content

    之后,发现只有第一个Item的convertview为null其他的不为空。

    虽然两种设置不同,结果也不同,但是convertview的机制没有变。

    其实到此为止我们可以总结出convertview的机制了,就是在初始显示的时候,每次显示一个item都调用一次getview方法但是每次调用的时候covertview为空(因为还没有旧的view),当显示完了之后。如果屏幕移动了之后,并且导致有些Item(也可以说是view)跑到屏幕外面,此时如果还有新的item需要产生,则这些item显示时调用的getview方法中的convertview参数就不是null,而是那些移出屏幕的view(旧view),我们所要做的就是将需要显示的item填充到这些回收的view(旧view)中去,最后注意convertview为null的不仅仅是初始显示的那些item,还有一些是已经开始移入屏幕但是还没有view被回收的那些item。

    最终我们用亲手写的代码实现了Recycler(反复循环器).


    第二个问题其实应该在第一个问题中嵌套来讲,但是为了思路清晰我分开了:

    view的setTag和getTag方法其实很简单,在实际编写代码的时候一个view不仅仅是为了显示一些字符串、图片,有时我们还需要他们携带一些其他的数据以便我们对该view的识别或者其他操作。于是android 的设计者们就创造了setTag(Object)方法来存放一些数据和view绑定,我们可以理解为这个是view 的标签也可以理解为view 作为一个容器存放了一些数据。而这些数据我们也可以通过getTag() 方法来取出来。

    到这里setTag和getTag大家应该已经明白了。再回到上面的话题,我们通过convertview的setTag方法和getTag方法来将我们要显示的数据来绑定在convertview上。如果convertview 是第一次展示我们就创建新的Holder对象与之绑定,并在最后通过return convertview 返回,去显示;如果convertview 是回收来的那么我们就不必创建新的holder对象,只需要把原来的绑定的holder取出加上新的数据就行了。


    至此我的问题讲完了,你的问题解决了么?

  • 相关阅读:
    C#磁吸屏幕窗体类库
    准备
    我写的诗
    How to turn off a laptop keyboard
    How to tell which commit a tag points to in Git?
    Why should I care about lightweight vs. annotated tags?
    How to get rid of “would clobber existing tag”
    Facebook, Google and Twitter threaten to leave Hong Kong over privacy law changes
    The need for legislative reform on secrecy orders
    Can a foreign key be NULL and/or duplicate?
  • 原文地址:https://www.cnblogs.com/misybing/p/4873511.html
Copyright © 2011-2022 走看看