Android(java)學習筆記88:BaseAdapter適配器重寫之getView()


1. BaseAdapter適配器重寫 之getView():

(1)View getview(int position, View convertview, ViewGroup parent )

第一個參數position----------該視圖在適配器數據中的位置 
第二個參數convertView-----舊視圖 
第三個參數parent------------此視圖最終會被附加到的父級視圖

特別注意:convertview參數

首先講下ListView的原理:ListView中的每一個Item顯示都需要Adapter調用一次getView的方法,這個方法會傳入一個convertView的參數,返回的View就是這個Item顯示的View。

如果當Item的數量足夠大,再為每一個Item都創建一個View對象,必將占用很多內存,創建View對象(mInflater.inflate(R.layout.lv_item, null);從xml中生成View,這是屬於IO操作)也是耗時操作,所以必將影響性能。

Android提供了一個叫做Recycler(反復循環器)的構件,就是當ListView的Item從上方滾出屏幕視角之外,對應Item的View會被緩存到Recycler中,相應的會從下方生成一個Item,而此時調用的getView中的convertView參數就是滾出屏幕的Item的View,所以說convertView 我們可以復用它,這樣就省去了new View的大量開銷。

 

(2)ViewHolder(自定義的):

getView方法:

public View getView(int position, View convertView, ViewGroup parent) { System.out.println("getView " + position + " " + convertView); ViewHolder holder = null; if (convertView == null) { convertView = mInflater.inflate(R.layout.lv_item, null); holder = new ViewHolder(); holder.textView = (TextView)convertView.findViewById(R.id.tv_text); convertView.setTag(holder); } else { holder = (ViewHolder)convertView.getTag(); } holder.textView.setText(mData.get(position)); return convertView; }

ViewHolder:

package com.shinylife.smalltools; import android.widget.ImageView; import android.widget.TextView; public class ViewHolder { public ImageView imgView; public TextView textView;
}

為什么要ViewHolder(自定義的)這樣一個東西, 因為無論convertView是不是null, 都需要對ViewHolder中的TextView和ImageView進行賦值操作, 貌似沒有什么必要.
其實不是這么簡單, 這樣做是一種拿空間換時間的方式. 增加一個對象ViewHolder , 卻省去了一系列的findViewById()的時間,家都知道, 在一個View的樹形結構上使用findViewById()查找控件是需要時間的, 而且這個樹形結構越復雜, 花費的時間越多。

注意:

我們都知道在getView方法中的操作是這樣的:先從xml中創建view對象inflate操作,我們采用了重用convertView方法優化),然后在這個view去findViewById,找到每一個子View,如:一個TextView等。

這里的findViewById操作是一個樹查找過程,也是一個耗時的操作,所以這里也需要優化,就是使用viewHolder,把每一個子View都放在Holder中,當第一次創建convertView對象時,把這些子view找出來。

然后用convertView的setTag將viewHolder設置到Tag中,以便系統第二次繪制ListView時從Tag中取出。當第二次重用convertView時,只需從convertView中getTag取出來就可以。

 

(3)setTag()/getTag():View中的setTag(Onbect)表示給View添加一個格外的數據,以后可以用getTag()將這個數據取出來

可以用在多個Button添加一個監聽器,每個Button都設置不同的setTag。這個監聽器就通過getTag來分辨是哪個Button 被按下:

 1 import android.app.Activity;  2 
 3  import android.os.Bundle;  4 
 5 import android.view.View;  6 
 7 import android.widget.Button;     8 
 9     public class Main extends Activity {    10 
11  @Override    12 
13            public void onCreate(Bundle savedInstanceState) {    14 
15                    super.onCreate(savedInstanceState);    16  setContentView(R.layout.main);   17  
18                    Button button1 = (Button) findViewById(R.id.Button01);    19                    Button button2 = (Button) findViewById(R.id.Button02);    20                    Button button3 = (Button) findViewById(R.id.Button03);    21                    Button button4 = (Button) findViewById(R.id.Button04);    22 
23                    MyListener listener = new MyListener();    24                    button1.setTag(1);    25  button1.setOnClickListener(listener);    26                   
27                    button2.setTag(2);    28  button2.setOnClickListener(listener);    29 
30                    button3.setTag(3);    31  button3.setOnClickListener(listener);    32 
33                    button4.setTag(4);    34  button4.setOnClickListener(listener);   35 
36  }    37 
38                 public class MyListener implements View.OnClickListener {    39 
40  @Override    41                          public void onClick(View v) {    42                               int tag = (Integer) v.getTag();    43 
44                              switch (tag) {    45                            case 1:    46                                       System.out.println("button1 click");   47                                     break;    48 
49                            case 2:    50                                        System.out.println("button2 click");    51                                        break;    52 
53                           case 3:    54                                        System.out.println("button3 click");    55                                        break;    56 
57                            case 4:    58                                        System.out.println("button4 click");    59                                        break;    60  }   61  }   62  } 63 
64 } 65             

在寫ListView 時候要重寫BaseAdapter:

 需要在沒個item都加上button 點擊button做相應操作

 這個時候需要button里面設置下 這行的屬性

button.setTag(item.user.name);

 然后處理button事件。

 這個東西在一些需要用到Adapter自定控件顯示方式的時候非常有用

Adapter 有個getView方法,可以使用setTag把查找的view緩存起來方便多次重用:

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

  ViewHolder vh;

  if (convertView == null) {

      LayoutInflater inflater = (LayoutInflater) mWidgetsSwitchApp.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

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

      vh = new ViewHolder();

      vh.view1 = (ImageView) convertView.findViewById(R.id.view1);

      vh.view2 = (ImageView) convertView.findViewById(R.id.view2);

      vh.view3 = (ImageView) convertView.findViewById(R.id.view3);

      vh.view4 = (ImageView) convertView.findViewById(R.id.view4);

      convertView.setTag(vh);

  } else {

      vh = (ViewHolder) convertView.getTag();

  }

  //其他的代碼可以直接使用 vh.view1、vh.view2、vh.view3 、vh.view4

  }

 

你可以看看android的源碼,特別有listview的,你就會發現這個函數很多時候有妙用!呵呵!

我的一點理解是,綁定數據,特別是綁定數據到view。而且可以用getTag()取得,很方便,而且是任意類型的數據,真的很酷。

在實例BaseAdapter()的getView(position, convertView, par)里有用到。convertView這里會用到setTag() getTag()。就可以生成convertView並復用里面的widget,一直覺得這個東西沒啥用setTag(),不過只要能用上 就是比較巧的了

在一個程序中呢 我有好多個button 我想點擊一個出現1, 點擊第二個出現2

 for (int i = 0; i < 20; i++) {

  cells[i] = (ImageView) findViewById(cellIDs[i]);

  cells[cellnumber++].setOnClickListener(new OnClickListener() {

          public void onClick(View v){

                 cellClicked(cellnumber, v);

      }});

  }

上面的代碼效率不高 而且 無論點擊哪一個都會出現21 當然這是我邏輯錯誤

那怎么實現呢

  OnClickListener listener = new OnClickListener() {

       public void onClick(View v) {

       int cellId = (Integer) v.getTag();

       cellClicked(cellId, v);

   }

 }

  View v;

  for (int i = 0; i < 20; i++) {

       v = findViewById(cellIDs[i]);

       v.setOnClickListener(listener);

       v.setTag(i);

  }

這樣呢就實例話一個listener,同時通過tag傳值就不是每一個實例都做了

 


免責聲明!

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



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