Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> [Android]對BaseAdapter中ViewHolder編寫簡化

[Android]對BaseAdapter中ViewHolder編寫簡化

編輯:關於Android編程

在Android項目中,經常都會用到ListView這個控件,而相應的Adapter中getView()方法的編寫有一個標准的形式,如下:   復制代碼  1 @Override  2     public View getView(int position, View convertView, ViewGroup parent) {  3         ViewHolder holder;  4         if(null == convertView){  5             holder = new ViewHolder();  6             LayoutInflater mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  7             convertView = mInflater.inflate(R.layout.item, null);  8             holder.btn = (Button) convertView.findViewById(R.id.btn);  9             holder.tv = (TextView) convertView.findViewById(R.id.tv); 10             holder.iv = (TextView) convertView.findViewById(R.id.iv); 11  12             convertView.setTag(holder); 13         }else{ 14             holder = (ViewHolder) convertView.getTag(); 15         } 16         final HashMap<String, Object> map = list.get(position); 17  18         holder.iv.setImageResource(Integer.valueOf(map.get("iv").toString())); 19         holder.tv.setText(map.get("tv").toString()); 20  21         holder.btn.setOnClickListener(new View.OnClickListener() { 22             @Override 23             public void onClick(View v) { 24                 Toast.makeText(context, map.get("btn").toString(), Toast.LENGTH_SHORT).show(); 25             } 26         }); 27  28         return convertView; 29     } 30  31 class ViewHolder{ 32         Button btn; 33         ImageView iv; 34         TextView tv; 35  36     } 復制代碼 以下是碎碎念(想直接看代碼的,就跳過這段吧-_-!):   也就是說每次編寫Adapter都需要編寫class ViewHolder...、if(null == convertView){...等等。這些代碼跟業務邏輯關系不大,沒有必要每次都寫重復代碼,   所以,顯然有簡化代碼的余地。   既然我們的需求是不需要重復編寫ViewHolder等內部類,那就把它移到父類吧。   但是ViewHolder中在實際項目中有不同的View,那就用list存放起來吧,但是放在list中的話,怎麼取出來?用index?顯然不是好的方法,不是有Resource Id這玩意,通過這個取不就好了麼?所以以Resource Id為key放在Map中比較合適,但是既然以int(Resource Id)為key,那自然而然想到使用SparseArray了。   然後再把if(null == converView)...這些代碼統統移到父類中。   所以ABaseAdapter誕生了,代碼如下:   復制代碼  1 /**  2  * 實現對BaseAdapter中ViewHolder相關的簡化  3  * Created with IntelliJ IDEA.  4  * Author: wangjie  email:[email protected]  5  * Date: 14-4-2  6  * Time: 下午5:54  7  */  8 public abstract class ABaseAdapter extends BaseAdapter{  9     Context context; 10  11     protected ABaseAdapter(Context context) { 12         this.context = context; 13     } 14  15     protected ABaseAdapter() { 16     } 17  18     /** 19      * 各個控件的緩存 20      */ 21     class ViewHolder{ 22         public SparseArray<View> views = new SparseArray<View>(); 23  24         /** 25          * 指定resId和類型即可獲取到相應的view 26          * @param convertView 27          * @param resId 28          * @param <T> 29          * @return 30          */ 31         <T extends View> T obtainView(View convertView, int resId){ 32             View v = views.get(resId); 33             if(null == v){ 34                 v = convertView.findViewById(resId); 35                 views.put(resId, v); 36             } 37             return (T)v; 38         } 39  40     } 41  42     /** 43      * 改方法需要子類實現,需要返回item布局的resource id 44      * @return 45      */ 46     public abstract int itemLayoutRes(); 47  48     @Override 49     public View getView(int position, View convertView, ViewGroup parent) { 50         ViewHolder holder; 51         if(null == convertView){ 52             holder = new ViewHolder(); 53             convertView = LayoutInflater.from(context).inflate(itemLayoutRes(), null); 54             convertView.setTag(holder); 55         }else{ 56             holder = (ViewHolder) convertView.getTag(); 57         } 58         return getView(position, convertView, parent, holder); 59     } 60  61     /** 62      * 使用該getView方法替換原來的getView方法,需要子類實現 63      * @param position 64      * @param convertView 65      * @param parent 66      * @param holder 67      * @return 68      */ 69     public abstract View getView(int position, View convertView, ViewGroup parent, ViewHolder holder); 70  71 } 復制代碼 如上代碼:增加了一個itemLayoutRes()的抽象方法,該抽象方法提供給子類實現,返回item布局的resource id,為後面的getView方法提供調用。   可以看到上述代碼中,在系統的getView方法中,進行我們以前在BaseAdapter實現類中所做的事(初始化converView,並綁定ViewHolder作為tag),然後拋棄了系統提供的getView方法,直接去調用自己寫的getView抽象方法,這個getView方法是提供給子類去實現的,作用跟系統的getView一樣,但是這個getView方法中攜帶了一個ViewHolder對象,子類可以通過這個對象進行獲取item中的控件。   具體使用方式如下,比如創建了MyAdapter並繼承了ABaseAdapter:   注意,在構造方法中需要調用父類的構造方法:   1 public MyAdapter(Context context, List<HashMap<String, Object>> list) { 2     super(context); 3     this.list = list; 4 } 即,以上的“super(context);”必須調用。   接著實現itemLayoutRes()方法,返回item的布局:   1 @Override 2 public int itemLayoutRes() { 3     return R.layout.item; 4 }     getView方法中的實現如下:   復制代碼  1 @Override  2 public View getView(int position, View convertView, ViewGroup parent, ViewHolder holder) {  3     final HashMap<String, Object> map = list.get(position);  4   5     Button btn = holder.obtainView(convertView, R.id.item_btn);  6     ImageView iv = holder.obtainView(convertView, R.id.item_iv);  7     TextView tv = holder.obtainView(convertView, R.id.item_tv);  8   9      btn.setOnClickListener(new View.OnClickListener() { 10         @Override 11         public void onClick(View v) { 12             Toast.makeText(context, map.get("btn").toString(), Toast.LENGTH_SHORT).show(); 13          } 14      }); 15  16      iv.setImageResource(Integer.valueOf(map.get("iv").toString())); 17      tv.setText(map.get("tv").toString()); 18  19         return convertView; 20     } 復制代碼 如上代碼:調用holder.obtainView方法既可獲取item中的控件;    
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved