1. 程式人生 > >Android ListView理解之BaseAdapter

Android ListView理解之BaseAdapter

ListView是Android開發過程中較為常見的元件之一,它將資料以列表的形式展現出來。一般而言,一個ListView由以下三個元素組 成:

1.View,用於展示列表,通常是一個xml所指定的。大家都知道Android的介面基本上是由xml檔案負責完成的,所以ListView的界 面也理所應當的使用了xml定義。例如在ListView中經常用到的“android.R.layout.simple_list_item_1”等, 就是Android系統內部定義好的一個xml檔案。

2.介面卡,用來將不同的資料對映到View上。不同的資料對應不同的介面卡,如ArrayAdapter,CursorAdapter, SimpleAdapter等, 他們能夠將陣列,指標指向的資料,Map等資料對映到View上。也正是由於介面卡的存在,使得ListView的使用相當靈活,經過介面卡的處理後,在 view看來所有的資料對映過來都是一樣的。3.資料,具體的別對映的資料和資源,可以是字串,圖片等,通過介面卡,這些資料將會被現實到 ListView上。所有的資料和資源要顯示到ListView上都通過介面卡來完成。

系統已有的介面卡可以將基本的資料顯示到ListView上,如:陣列,Cursor指向的資料,Map裡的資料。但是在實際開發中這些系統已實現 的介面卡,有時不能滿足我們的需求。而且系統自帶的含有多選功能ListView在實際使用過程中會有一些問題。要實現複雜的ListView可以通過繼 承ListView並重寫相應的方法完成,同時也可以通過繼承BaseAdapter來實現。通過文件可以看出,ArrayAdapter,CursorAdapter, SimpleAdapter都繼承於BaseAdapter。所以通過繼承BaseAdapter就可以完成自己的Adapter,可以將任何複雜組合的資料和資源,以任何你想要的顯示效果展示給大家。

繼承BaseAdapter之後,需要重寫以下四個方法:getCount,getItem,getItemId,getView。

ListView繪製的過程如下:首先,系統在繪製ListView之前,將會先呼叫getCount方法來獲取Item的個數。之後每繪製一個 Item就會呼叫一次getView方法,在此方法內就可以引用事先定義好的xml來確定顯示的效果並返回一個View物件作為一個Item顯示出來。也 正是在這個過程中完成了介面卡的主要轉換功能,把資料和資源以開發者想要的效果顯示出來。也正是getView的重複呼叫,使得ListView的使用更 為簡單和靈活。這兩個方法是自定ListView顯示效果中最為重要的,同時只要重寫好了就兩個方法,ListView就能完全按開發者的要求顯示。而 getItem和getItemId方法將會在呼叫ListView的響應方法的時候被呼叫到。所以要保證ListView的各個方法有效的話,這兩個方 法也得重寫。比如:沒有完成getItemId方法的功能實現的話,當呼叫ListView的getItemIdAtPosition方法時將會得不到想 要的結果,因為該方法就是呼叫了對應的介面卡的getItemId方法。

另外,對於setTag方法是幹什麼的,SDK解釋為

Tags

Unlike IDs, tags are not used to identify views. Tags are essentially an extra piece of information that can be associated with a view. They are most often used as a convenience to store data related to views in the views themselves rather than by putting them in a separate structure.

Tag不像ID是用標示view的。Tag從本質上來講是就是相關聯的view的額外的資訊。它們經常用來儲存一些view的資料,這樣做非常方便而不用存入另外的單獨結構。

convertView中的TAG

1.  對於使用了LayoutInflater物件進行View擴充的Tag的使用

public View getView(int position, View convertView, ViewGroup parent) {

       ViewHolder holder = null;

       if (convertView == null) {

          holder = new ViewHolder();

          convertView = inflater.inflate(R.layout.vlist2, null);

          holder.img = (ImageView) convertView.findViewById(R.id.img);

          holder.title = (TextView) convertView.findViewById(R.id.title);

           holder.info = (TextView)

convertView.findViewById(R.id.info);

          // setTag的妙用

          convertView.setTag(holder);

       } else {

          // setTag的妙用

          holder = (ViewHolder) convertView.getTag();

       }

 ……略

}

首先我們要知道setTag方法是幹什麼的,他是給View物件的一個標籤,標籤可以是任何內容,我們這裡把他設定成了一個物件,因為我們是把vlist2.xml的元素抽象出來成為一個類ViewHolder,用了setTag,這個標籤就是ViewHolder例項化後物件的一個屬性。我們之後對於ViewHolder例項化的物件holder的操作,都會因為java的引用機制而一直存活並改變convertView的內容,而不是每次都是去new一個。我們就這樣達到的重用——我希望我說清楚了。如果有更簡單的解釋,請指教。

這是我們在Adapter中的使用,那麼我們在這裡不使用Tag標籤會怎麼樣呢?

我們試想,如果我們不用Tag標籤,那麼我們的物件如何與convertView快取結合並達到合理的效率利用?貌似答案並不明朗——所以使用Tag是比較明智的做法。

2.  對於沒有使用LayoutInflater物件進行View擴充的Tag的使用。

if (convertView != null) {

  view = convertView;

  ...

  } else {

  view = new Xxx(...);

  ...

  }

這是我們的程式,我們看到,貌似沒有用Tag——是的,當沒有使用LayoutInflater進行View的擴充的時候,是沒有必要用的,雖然也可以用。