[Android]對BaseAdapter中ViewHolder編寫簡化

來源:互聯網
上載者:User

在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             @Override23             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     class ViewHolder{22         public SparseArray<View> views = new SparseArray<View>();23 24         /**25          * 指定resId和類型即可擷取到相應的view26          * @param convertView27          * @param resId28          * @param <T>29          * @return30          */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 id44      * @return45      */46     public abstract int itemLayoutRes();47 48     @Override49     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 position64      * @param convertView65      * @param parent66      * @param holder67      * @return68      */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 @Override2 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         @Override11         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中的控制項;  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.