打造通用的适配器
以前的适配器
一目十行随便扫描一下.不想看的此处可以直接跳过
public class ScanBarItemAdapter extends BaseCommonAdapter<HashMap<String, String>>
{
private Viewholder viewHolder;
public ScanBarItemAdapter(Activity activity)
{
super(activity);
}
@Override
protected View getLayoutView(int position, View convertView, ViewGroup parent)
{
if (convertView == null)
{
viewHolder = new Viewholder();
convertView = LayoutInflater.from(activity).inflate(R.layout.desk_ly_scan_bar_item, parent, false);
viewHolder.tvCommonName = convertView.findViewById(R.id.tvCommonName);
viewHolder.tvConsistency = convertView.findViewById(R.id.tvConsistency);
viewHolder.tvPosition = convertView.findViewById(R.id.tvPosition);
viewHolder.tvModel = convertView.findViewById(R.id.tvModel);
viewHolder.tvVolumn = convertView.findViewById(R.id.tvVolumn);
convertView.setTag(viewHolder);
}
else
{
viewHolder = (Viewholder) convertView.getTag();
}
viewHolder.tvCommonName.setText(item.get(position).get(Constant.CommonName));
viewHolder.tvConsistency.setText(item.get(position).get(Constant.Consistency));
viewHolder.tvPosition.setText(item.get(position).get(Constant.Position));
viewHolder.tvModel.setText(item.get(position).get(Constant.Model));
viewHolder.tvVolumn.setText(item.get(position).get(Constant.Volumn));
return convertView;
}
private class Viewholder
{
TextView tvCommonName;
TextView tvConsistency;
TextView tvPosition;
TextView tvModel;
TextView tvVolumn;
}
}
通过我们的瞄一眼,可以看出我们及时对已上的适配器进行泛型封装但是我们还是逃不过需要在每一个适配器中些VIewHolder类
若是一个大型的项目,可能我们的精力大部分用在写适配器上面,我们需要大量重复viewHolder.tvCommonName.setText
,viewHolder.tvCommonName.setText
…等等等,写我自己都想吐, 那有没有一种办法,让我们不在为每一个适配器写一个Viewholder类
呢,有,当然有.下面我们就来看看通用的ViewHolder类
ViewHolder
import androidx.annotation.NonNull;
public class ViewHolder
{
private final SparseArray<View> sparseArray;
private View mConvertView;
private ViewHolder(Context context, ViewGroup parent, int layoutId)
{
this.sparseArray=new SparseArray<>();
mConvertView= LayoutInflater.from(context).inflate(layoutId,parent,false);
mConvertView.setTag(this);
}
public static ViewHolder get(Context context,int position, View convertView, ViewGroup parent, int layoutId)
{
if (convertView == null)
{
return new ViewHolder(context,parent,layoutId);
}
return (ViewHolder) convertView.getTag();
}
public <T extends View> T getView(@NonNull int viewId)
{
View view=sparseArray.get(viewId);
if (view == null)
{
view = mConvertView.findViewById(viewId);
sparseArray.put(viewId,view);
}
return (T) view;
}
public View getConvertView()
{
return mConvertView;
}
}
在ViewHolder中的这段代码等同于以前的这段代码(红线标注的地方)
红线中间的效果我们用ViewHolder中的getView代替
用法
我们可以再封装一个通用BaseCommonAdapter类
public abstract class BaseCommonAdapter<T> extends BaseAdapter
{
protected ArrayList<T> item=new ArrayList<>();
protected Activity activity;
protected int layoutId;
public BaseCommonAdapter(Activity activity,int layoutId)
{
this.activity=activity;
this.layoutId=layoutId;
}
@Override
public int getCount()
{
return item.size();
}
@Override
public T getItem(int position)
{
return item.get(position);
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder viewHolder=ViewHolder.get(activity,position,convertView,parent,layoutId);
convert(viewHolder,getItem(position));
return viewHolder.getConvertView();
}
protected abstract void convert(ViewHolder viewHolder, T item);
public void setItem(ArrayList<T> item)
{
if (item != null && item.size() > 0)
{
this.item.clear();
this.item.addAll(item);
}
}
}
因为在getView()方法中,我们每次都需要重新ViewHolder viewHolder=ViewHolder.get(activity,position,convertView,parent,layoutId);
以及return部分,所以我们直接在BaseCommonAdapter中写死, 利用构造方法把需要加载的布局ID传递进来,所以我们直接在定义一个convert抽象方法就可以了,然后在我们的adapter中进行实现
自己的adapter
public class BoxSpinnerAdapter extends BaseCommonAdapter<ArrayList<String>>
{
public BoxSpinnerAdapter(Activity activity, int layoutId)
{
super(activity,layoutId);
}
@Override
protected void convert(ViewHolder viewHolder, ArrayList<String> item)
{
TextView tvId=viewHolder.getView(R.id.tvId);
tvId.setText(item.get(0));
TextView tvName=viewHolder.getView(R.id.tvName);
tvName.setText(item.get(1));
}
用法是不是很简单呢
我们再看看activity中的怎么调用这个适配器
BoxSpinnerAdapter adapter = new BoxSpinnerAdapter(getMyActivity(),R.layout.desk_rk_item_box);
adapter.setItem(boxArray);
mBinding.spinBox.setAdapter(adapter);
是不是瞬间减少了好多重复代码
终极封装
从上面看,我们还是需要写很多为控件设置属性的代码
在Adapter中我们常用的控件无非就是TextView
,ImageView
, Button
,这一部分我们可以再次封装
我们只需要在ViewHolder中添加一下方法即可
public class ViewHolder
{
//.........
//.........
//省略无关紧要代码
//.........
//.........
/**
* 设置TextView文本
* @param viewId 控件id
* @param text
* @return
*/
public ViewHolder setText(int viewId,String text)
{
TextView view =getView(viewId);
view.setText(text);
return this;
}
/**
* 设置字体颜色
* @param viewId
* @param colorId
* @return
*/
public ViewHolder setTextColor(int viewId,@ColorInt int colorId)
{
TextView view =getView(viewId);
view.setTextColor(colorId);
return this;
}
public ViewHolder setOnclickListener(int viewId,View.OnClickListener listener)
{
Button view=getView(viewId);
view.setOnClickListener(listener);
return this;
}
public ViewHolder setImagerDrawable(int viewId,@DrawableRes int drawableId)
{
ImageView view=getView(viewId);
view.setImageResource(drawableId);
return this;
}
}
完整代码–>拿来即用
ViewHolder类
import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.ColorInt;
import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes;
import androidx.annotation.NonNull;
public class ViewHolder
{
private final SparseArray<View> sparseArray;
private View mConvertView;
private ViewHolder(Context context, ViewGroup parent, int layoutId)
{
this.sparseArray=new SparseArray<>();
mConvertView= LayoutInflater.from(context).inflate(layoutId,parent,false);
mConvertView.setTag(this);
}
/**
* 获取ViewHolder 如果convertView为空则重新实例化一个ViewHolder赋值给convertView,否则从已有的convertView中获取ViewHolder
* @param context 上下文
* @param position 位置
* @param convertView convertView
* @param parent 父布局控件
* @param layoutId 布局id
* @return
*/
public static ViewHolder get(Context context,int position, View convertView, ViewGroup parent, int layoutId)
{
if (convertView == null)
{
return new ViewHolder(context,parent,layoutId);
}
return (ViewHolder) convertView.getTag();
}
/**
* 获取控件
* @param viewId 控件的Id
* @param <T>
* @return
*/
public <T extends View> T getView(@NonNull int viewId)
{
View view=sparseArray.get(viewId);
if (view == null)
{
view = mConvertView.findViewById(viewId);
sparseArray.put(viewId,view);
}
return (T) view;
}
/**
* 获取convertView
* @return
*/
public View getConvertView()
{
return mConvertView;
}
/**
* 设置TextView文本
* @param viewId 控件id
* @param text
* @return
*/
public ViewHolder setText(int viewId,String text)
{
TextView view =getView(viewId);
view.setText(text);
return this;
}
/**
* 设置字体颜色
* @param viewId
* @param colorId
* @return
*/
public ViewHolder setTextColor(int viewId,@ColorInt int colorId)
{
TextView view =getView(viewId);
view.setTextColor(colorId);
return this;
}
public ViewHolder setOnclickListener(int viewId,View.OnClickListener listener)
{
Button view=getView(viewId);
view.setOnClickListener(listener);
return this;
}
public ViewHolder setImagerDrawable(int viewId,@DrawableRes int drawableId)
{
ImageView view=getView(viewId);
view.setImageResource(drawableId);
return this;
}
}
BaseCommonAdapter类
import android.app.Activity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.ArrayList;
public abstract class BaseCommonAdapter<T> extends BaseAdapter
{
protected ArrayList<T> item=new ArrayList<>();
protected Activity activity;
protected int layoutId;
public BaseCommonAdapter(Activity activity,int layoutId)
{
this.activity=activity;
this.layoutId=layoutId;
}
@Override
public int getCount()
{
return item.size();
}
@Override
public T getItem(int position)
{
return item.get(position);
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent)
{
ViewHolder viewHolder=ViewHolder.get(activity,position,convertView,parent,layoutId);
convert(viewHolder,getItem(position));
return viewHolder.getConvertView();
}
protected abstract void convert(ViewHolder viewHolder, T item);
public void setItem(ArrayList<T> item)
{
if (item != null && item.size() > 0)
{
this.item.clear();
this.item.addAll(item);
}
}
}