[Android]對BaseAdapter中ViewHolder編寫簡化


以下內容為原創,歡迎轉載,轉載請注明

來自天天博客:http://www.cnblogs.com/tiantianbyconan/p/3642849.html

 

在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:tiantian.china.2@gmail.com
 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     public 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         public <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中的控件;

 

 


免責聲明!

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



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