關於BaseAdapter的使用及優化心得(一)


 

  對於Android程序員來說,BaseAdapter肯定不會陌生,靈活而優雅是BaseAdapter最大的特點。開發者可以通過構造BaseAdapter並搭載到ListView或者GridView這類多控件布局上面,實現軟件所需要的布局效果。同時,BaseAdapter也是適配器里面最基礎的一個類,其他的例如SimpleAdapter、ArrayAdapter都是直接或者間接繼承BaseAdapter,所以說學好BaseAdapter基本就熟練掌握了適配器的使用了。

  本文需要具備一些Android基礎知識的前提下才能更好的理解,因為本文並不是介紹BaseAdapter的基本使用方法,如果對於BaseAdapter不了解可以去參考一下文檔。在這里主要是介紹一下BaseAdapter的實現細節和怎么優化BaseAdapter的設計,從而節省我們寶貴的手機運行資源。對於老鳥高手來說,這可能是一個常識了,還是主要給那些像我以前一樣剛剛入門的開發者的一點點參考,也希望高手來多多指正。

 話不多說,我們看一看某些社交軟件的界面(網上找的。。。。。)

  這個列表項就是用ListView作為布局,搭載SimpleAdapter或者BaseAdapter作為數據源做成的界面效果。一般來說,很多軟件的界面都運用這個方法來實現想要的布局效果。我在這里說明一下后面說到的名詞,首先這是一個列表項,里面有各個數據項,例如圖片+文件傳輸助手+test+時間就是一個數據項,它是一個View視圖,這張圖片里面一共就有8個數據項,由8個View視圖按垂直方向排列而成。OK,我們開始步入正題。

  假設,我們還是用例子講解比較好理解,所以呢我們假設這個列表里面一共有40個數據項,而作為手機界面的限制,它一次只能顯示8個數據項,同時它的另外32個數據項是隱藏狀態。而顯示這8個數據項就需要8個View實例,也就是需要實例化8個View的子類來顯示內容,此時系統就有8個View實例占據內存空間。那如果我們把手指往下一滑動呢,自然頂端的數據項就會被隱藏,而底端的數據項自然就顯示出來,那么這時候需要在new一個新的View實例來嗎?如果還是繼續創建實例,那么系統內存空間就有9個View實例了,可是我們還是只需要8個View實例就可以在手機屏幕完全顯示,而頂端的被隱藏的實例話是可以不存在的了。所以這么來說,這樣就浪費了手機的運行資源了。

  為了解決這個問題,我們在BaseAdapter中可以對View進行重用,也就是將被隱藏的View改變為將要顯示的View並返回出來。

  在BaseAdapter中,這個抽象方法非常重要,它就是根據position的值返回對象的數據項的View視圖,所以我們主要也是圍繞這個方法來達到效率上優化的目的。

   public View getView(int position, View convertView, ViewGroup parent) { return null; } 

  簡單介紹一下這個函數的參數,position是ID索引值,也就是ListView的對應的數據項的序號,而convertView則是View視圖復用的基礎,如果為第一個頁面的數據,它的值為null,所以我們可以根據convertView的值來決定我們是否要new一個View的實例出來

參見下面代碼

 1 @Override  2 public View getView(int position, View convertView, ViewGroup parent) {  3   if(convertView == null){  4     convertView = new TextView(context);//新建一個字符串控件  5     ((TextView)convertView).setText(position);//實現其是第幾個數據項  6   }  7   else{  8     ((TextView)convertView).setText(position);//重新修改其是第幾個數據項  9   } 10   return convertView; 11 }

  為了簡單起來,我這里的View只是一個簡簡單單的字符串控件,在代碼中我們可以看到,先對convertView進行判斷,如果其值為null,則說明該方法此時返回的View是第一頁的視圖,所以需要new出一個View的實例,然后對其進行設置顯示的內容並返回(這里設置的內容為position)。如果其值不為null,則說明此時的View視圖是可以復用其他已經隱藏的View實例,而convertView的索引就是這個隱藏的實例,自然我們不用重新創建一個新的View實例而直接對convertView進行重新設置數值並返回便可。

  這樣就保證了程序里面只有足夠界面顯示的View實例的個數存在,而不會有多余的View來占用系統資源,由此也提高了一點點效率。

 

 

 

 

  這是BaseAdapter的效率優化的一個方面,接下來我們還要說一下另外一個方面,說明白了也就是一個小技巧來提高效率。對於一個BaseAdapter來說,顯示的界面肯定不是僅僅的一兩個字符串控件(不然我們就用ArrayAdapter了多簡便),而一般是加載一個根據layout生成的布局控件,相對來說這個的布局控件會比較復雜,我們會對其的子控件進行獲取並賦值返回,所以我們經常要調用findViewById()這個方法來或者子控件的引用。而findViewById()會比較消耗系統資源,頻繁的調用在我們快速滑動界面時會加重手機的負擔,所以我們也可以對這個地方進行一些小小的改進。

參考這個代碼

 1 public class PersonAdapter extends BaseAdapter {
 2     private List<Person> persons;//綁定的數據
 3     private int resource;//綁定的Layout數據項界面
 4     private LayoutInflater inflater;//布局填充服務
 5     
 6     public PersonAdapter(Context context, List<Person> persons, int resource) {
 7         this.persons = persons;
 8         this.resource = resource;
 9         inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
10     }
11     @Override
12     public int getCount() {
13         return persons.size();
14     }
15     @Override
16     public Object getItem(int position) {
17         return persons.get(position);
18     }
19     @Override
20     public long getItemId(int position) {
21         return position;
22     }
23     @Override
24     public View getView(int position, View convertView, ViewGroup parent) {
25         TextView nameView = null;
26         TextView phoneView = null;
27         if(convertView == null){
28             convertView = inflater.inflate(resource, null);//生成綁定數據的View界面
29             nameView = (TextView) convertView.findViewById(R.id.name);
30             phoneView = (TextView) convertView.findViewById(R.id.phone);
31             
32             ViewCache cache = new ViewCache();
33             cache.nameView = nameView;
34             cache.phoneView = phoneView;        
35             convertView.setTag(cache);
36         }else{
37             ViewCache cache = (ViewCache) convertView.getTag();
38             nameView = cache.nameView;
39             phoneView = cache.phoneView;
40         }
41         Person person = persons.get(position);
42         //下面代碼實現數據綁定
43         nameView.setText(person.getName());
44         phoneView.setText(person.getPhone());
45         
46         return convertView;
47     }
48     /**
49     *保存findViewById獲得的子控件索引的內部類
50     */
51     private final class ViewCache{
52         public TextView nameView;
53         public TextView phoneView;
54     }
55 }

  重點還是放在getView()這個方法上。在代碼里面,我寫了一個ViewCache的私有內部類,主要用來保存要來復用的View所需要獲得的子控件的索引值。稍微解釋一下代碼,如果convertView為null,則說明需要new出一個View實例,在這里就是調用Inflater這個系統服務根據resource這個界面的ID值來生成一個View實例,然后用findViewById這個方法來或者其中的子控件的值,並保存在內部類ViewCache中,放入Tag中,setTag(object)是可以放入一個任意的類來保存成為緩存,因為其是Object。最后設置View子控件的內容並返回。如果不為null呢,現在則需要重用View實例了,所以我們也順帶重用一下保存在Tag里面的ViewCache的類成員變量的子控件索引值,而不需要重新去一個一個調用findViewById()這個方法,在界面足夠復雜時這樣是可以節省很多系統資源的。

  這就是BaseAdapter提高效率的兩種小技巧,如果大牛有其他更好的技巧,也希望能分享分享用來學習一下。

 

作者:enjoy風鈴
出處:http://www.cnblogs.com/net168/
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則下次不給你轉載了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM