BaseAdapter中重寫getview的心得以及發現convertView回收的機制

來源:互聯網
上載者:User

以前一直在用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


<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="fill_parent"    android:layout_height="fill_parent"    android:orientation="vertical" >    <ListView        android:id="@+id/result"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:cacheColorHint="#00000000" ></ListView></LinearLayout>

此處注意ListView的android:layout_height屬性值為"fill_paternt",如果為“wrap_content"將會是另一種情況

adapter的代碼ListViewAdapter.java 

class ListViewAdapter extends BaseAdapter   {    private Context mContext;    int i=0;    public ListViewAdapter (Context context)    {    this.mContext=context;    }@Overridepublic int getCount(){return 30;}@Overridepublic Object getItem(int position){                return position;}@Overridepublic long getItemId(int position){                return 0;}    @Overridepublic View getView(int position, View convertView, ViewGroup parent){         System.out.println("getView " + position + " " + convertView);//調試語句         Holder holder;if(null==convertView){holder=new Holder();convertView=LayoutInflater.from(mContext).inflate(R.layout.textview, null); //mContext指的是調用的Activttyholder.textView=(TextView)convertView.findViewById(R.id.textview);convertView.setTag(holder);}else{holder=(Holder)convertView.getTag();}holder.textView.setText("position: "+position);        return convertView;      }class Holder{public TextView textView;}    }

運行程式之後發現螢幕上顯示出的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取出加上新的資料就行了。


至此我的問題講完了,你的問題解決了嗎?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.