封裝能重用的自定義Adapter,向翔哥致敬
來源:程序員人生 發布時間:2015-06-24 07:59:35 閱讀次數:4371次
看了翔哥的自定義萬能的adapter,自己也做下筆記,分析1下高手的思惟方式,讓我們1起進入變態程序員的內心世界。
分析萬能的adapter之前,我們先分析1下普通的adapter
public class ReportSpinnerAdapter extends BaseAdapter {
private Context context;
private List<String> str;
public ReportSpinnerAdapter(Context context, List<String> str, int textWidth) {
this.context = context;
this.str = str;
this.textWidth = textWidth;
}
@Override
public int getCount() {
return str.size();
}
@Override
public Object getItem(int position) {
return str.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
Viewholder hold;
if (convertView==null){
convertView = LayoutInflater.from(context).inflate(R.layout.spinner_layout,parent,false);
hold = new ViewHold();
hold.textView = (TextView) convertView.findViewById(R.id.textView);
convertView.setTag(hold);
}else{
hold = (ViewHold) convertView.getTag();
}
hold.textView.setText(str.get(position));
return convertView;
}
static class ViewHolder{
TextView textView;
}
普通的adapter大致就分為兩點,getView和ViewHolder,1個類就解決問題,觸及到控件的復用,就用到了ViewHolder,主要邏輯還是都在getView中,,如果對這個不理解,可以先百度ViewHolder,getView中的邏輯就是如果convertView第1次被使用的時候,初始化綁定布局,并設置標記,否則,就從convertView取出viewHolder,如果要更改布局中控件的參數就從viewHolder中取出控件設置參數,由于這個控件在convertView初始化的時候就1起初始化了,所以直接設置參數就ok了。這是1個標準程序員的通常做法,但是,這樣如果我們程序中要常常使用adapter,每一個Listview或GridView都要去弄1個adapter,就白白浪費了大量的時間,作為1個變態程序員,翔哥怎樣能忍,所以就出了這么1篇博客翔哥博客,讓我們也能從中獲利,收獲了新技術也收獲了新的思惟方式。
總結自定義萬能的adapter,或叫做可重用的adapter,分拆開來看,就是3點:
1.封裝1個特殊的ViewHolder,可以傳入參數就直接得到viewHolder,把這步干掉:
if (convertView==null){
convertView = LayoutInflater.from(context).inflate(R.layout.spinner_layout,parent,false);
hold = new ViewHold();
hold.textView = (TextView) convertView.findViewById(R.id.textView);
convertView.setTag(hold);
}else{
hold = (ViewHold) convertView.getTag();
}
想要干掉這1步,就要想到,傳入甚么樣的參數,才能直接得到viewHolder呢,就是后面這幾個,1.LayoutInflater.from(context) 2.R.layout.spinner_layout 3.parent 4.convertView
知道了需要的條件就好說了,直接寫1個
public class ViewHolder {
private SparseArray<View> views;
private View convertView;
public ViewHolder(ViewGroup parent,LayoutInflater inflater,int layoutId) {
this.views = new SparseArray<View>();
this.convertView = inflater.inflate(layoutId,parent,false);
this.convertView.setTag(this);
}
/**
* 得到viewHolder
* @param parent
* @param convertView
* @param inflater
* @param layoutId
* @return
*/
public static ViewHolder getViewHolder(ViewGroup parent,View convertView,LayoutInflater inflater,int layoutId){
if (convertView==null){
return new ViewHolder(parent,inflater,layoutId);
}
return (ViewHolder) convertView.getTag();
}
這個 SparseArray<View> views實際上就是1個鍵值對,用來保存listview或gridview上每行或每列上的所有控件的,效力上要高于hashmap,用法就是
/**
* 根據Id得到view
* @param viewId
* @param <T>
* @return
*/
public <T extends View>T getView(int viewId){
View view = views.get(viewId);
if (view==null){
view = convertView.findViewById(viewId);
views.put(viewId,view);
}
return (T) view;
}
這樣,1個ViewHolder就弄定了。
2.編寫1個通用的adapter,通用adapter,基本沒法實現,那怎樣辦呢,做1個半通用的adapter,既然要半通用,就是大體相同,少數差異,那用抽象類繼承的方式就最好了
public abstract class CommonAdapter<T> extends BaseAdapter {
private List<T> list;
private LayoutInflater inflater;
private int layoutId;
public CommonAdapter(List<T> list, Context context,int layoutId) {
this.list = list;
this.inflater = LayoutInflater.from(context);
this.layoutId = layoutId;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = ViewHolder.getViewHolder(parent,convertView,inflater,layoutId);
convert(viewHolder,list.get(position));
return viewHolder.getConvertView();
}
public abstract void convert(ViewHolder viewHolder,T t);
}
首先,我們綁定adapter的時候不肯定數據源,就得用泛型類和泛型集合了,再就是傳入布局id和context上下文,把需要給控件賦值的地方設置為抽象方法,給子類繼承,這樣封裝好了以后,我們需要做的事情就是少之又少了,只需要重寫convert方法和構造方法了
public class MyAdapter extends CommonAdapter<Bean> {
public MyAdapter(List<Bean> list, Context context, int layoutId) {
super(list, context, layoutId);
}
@Override
public void convert(ViewHolder viewHolder, Bean bean) {
((TextView)viewHolder.getView(R.id.text)).setText("這是測試數據1");
((TextView)viewHolder.getView(R.id.text)).setText("這是測試數據1"); }
}
這樣,只需要在activity或fragment中進行綁定MyAdapter,把數據和布局id和content傳入就弄定了。只不過(viewHolder.getView(R.id.text)).setText這類寫法很蛋疼,代碼中寫強轉的話,還要把光標切回來,反正我個人是很不習慣的,那怎樣辦呢,可以這樣,我們既然有了viewholder對象,我們就改造1下viewHolder對象,讓公共代碼多1點,我們以后重復寫的地方就少1點。在ViewHolder中加入以下方法
/**
* 根據id得到TextView
* @return
*/
public TextView getTextView(int viewId){
return getView(viewId);
}
/**
* 根據id得到ImageView
* @return
*/
public ImageView getImageView(int viewId){
return getView(viewId);
}
/**
* 根據id得到Button
* @return
*/
public Button getButton(int viewId){
return getView(viewId);
}
/**
* 根據id得到RadioButton
* @return
*/
public RadioButton getRadioButton(int viewId){
return getView(viewId);
}
/**
* 根據id得到CheckBox
* @return
*/
public CheckBox getCheckBox(int viewId){
return getView(viewId);
}
/**
* 根據id得到ImageButton
* @return
*/
public ImageButton getImageButton(int viewId){
return getView(viewId);
}
/**
* 根據id得到ImageButton
* @return
*/
public EditText getEditText(int viewId){
return getView(viewId);
}
那末我們的Myadapter中的convert方法就能夠這樣寫了
@Override
public void convert(ViewHolder viewHolder, Bean bean) {
viewHolder.getTextView(R.id.text).setText("這是測試數據1");
viewHolder.getTextView(R.id.text).setText("這是測試數據2");
}
這樣書寫起來就會流暢1點,比較跟手,好了,這基本就是翔哥萬能的自定義adapter的主要內容,下面圖解1下核心思想
最后,源碼:點擊打開鏈接
生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈