今天在CSDN博客上看到了hongyang大神写的关于打造Listiew通用适配器的博客,感觉非常厉害着手仿照封装了自己的通用适配器(站在巨人肩膀上就是不一样 嘎嘎嘎)对于以后的开发非常有用可以省掉很多代码和时间。大神的原文地址:http://blog.csdn.net/lmj623565791/article/details/38902805
特地写篇自己的博客记录下自己的理解。
通用适配器逻辑:
1、通用ViewHolder:
a、通用ViewHolder主要处理两件事:adapter中的convertView和item中的各个布局控件
b、起一个View变量存储convertView,采用SparseArray<View> sparseArray来存储item布局中的
每一个View 。SparseArray类似于HashMap但效率又比HashMap要高,而且里面的存储格式是key--Integer value--object
所以正好存储item中布局的控件 key--存储控件id value--存储控件本身 key--id value--view
c、在进行构造实例的时候采用convertView来进行判断根据是否为null来判断是否需要构造新的实例
d、从ConvertView中得到item布局中的View
i、实例化ConvetView后下一步就是从这个item布局ConvertView中得到item布局中的控件
直接从SparseArray中得到如果在这个集合中没有得到的话就直接从布局中通过findViewById来得到
i、为了保障获取item中View的通用性,采用泛型来进行构建,<T extends View> T getView(){} 这个函数这样进行构建返回各种类型的控件如 TextView ImageView ListView等
2、通用适配器:
a、通用适配器也和BaseAdapter一样采用abstract类型,留出根据不同业务进行不同操作的入口
b、考虑到每一个适配器的数据集合的不同 在通用适配器中的数据集合也采用一个具有公共数据结构的数据集合--泛型
c、每一个数据集合为用户自主定义,所以在通用适配器中的abstract方法(其他适配器根据自身需求实现的方法)中将这个数据返回
根据自己的特性来进行实现
3、通用适配器调用:
a、通用适配器调用不需要进行继承直接调用即可
- 贴一段通用ViewHolder代码:
/**
1. 公共ViewHolder 作为CommAdapter公共适配器的基础
*/
public class CommViewHolder {
private View mConvertView;//存储adapter中的convertView--itemView
private SparseArray<View> viewArrays;//存储itemView中的布局控件 key--id value-view
/**
* 实例化CommViewHolder
* **/
private CommViewHolder(Context context,int itemViewResource){
this.mConvertView= LayoutInflater.from(context).inflate(itemViewResource,null);
this.viewArrays=new SparseArray<>();
this.mConvertView.setTag(this);
}
/**
* 根据外部传入的convertView是否为null来判断
* 是否需要实例化CommViewHolder
* **/
public static CommViewHolder obtainHolder(Context context,View convertView,int itemViewResorce){
if(convertView==null){
return new CommViewHolder(context,itemViewResorce);
}else{
return (CommViewHolder)convertView.getTag();
}
}
/**
* 根据View的id来获取View本身
* **/
public <T extends View> T getView(int viewId ){
View view=viewArrays.get(viewId);
if(view==null){
view=mConvertView.findViewById(viewId);
if(view!=null){
viewArrays.put(viewId,view);
}
}
return (T)view;
}
/**
* 获取convertView
* **/
public View getConvertView(){
return mConvertView;
}
/**
* 为控件设置文本
* **/
public void setText(int viewId,String text){
TextView textView=getView(viewId);
if(null!=textView && !Utils.IsEmptyOrNullString(text)){
textView.setText(text);
}
}
/**
* 设置图片
* **/
public void setImageView(int viewId,String url,int defaultDrawable){
ImageView imageView=getView(viewId);
if(null!=imageView && !Utils.IsEmptyOrNullString(url)){
Picasso.with(IshehuiSeoulApplication.app).load(url).
placeholder(IshehuiSeoulApplication.resources.getDrawable(defaultDrawable)).
transform(IshehuiSeoulApplication.mCircleTransformation).into(imageView);
}
}
再贴一段通用适配器代码:
/**
* 公共适配器
* 使用说明:
* a、使用不需要继承直接创建
*/
public abstract class CommAdapter<T> extends BaseAdapter {
private Context mContext;
private List<T> commDatas=new ArrayList<>();//数据集合
private int itemViewResource;
public CommAdapter(Context context,List<T> commDatas,int itemViewResource){
this.mContext=context;
this.commDatas=commDatas;
this.itemViewResource=itemViewResource;
}
@Override
public int getCount() {
return commDatas.size();
}
@Override
public Object getItem(int position) {
return commDatas.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
CommViewHolder holder=CommViewHolder.obtainHolder(mContext,convertView,itemViewResource);
convertView(holder,commDatas.get(position),position);
return holder.getConvertView();
}
/**根据实际的业务需求来实现的方法**/
public abstract void convertView(CommViewHolder holder,T data,int position);
}
最后上一段实际调用的逻辑:
//将公共适配器设置到列表上
mTopListView.setAdapter(mAdapter = new CommAdapter<DomainInfoEx(getActivity(),mHotDomainList,R.layout.hot_top_domain_item) {
@Override
public void convertView(CommViewHolder holder, DomainInfoEx domainInfo, int position) {
holder.setText(R.id.plant_name, domainInfo.getName());
holder.setText(R.id.plant_content_count, domainInfo.getHouseCountText());
String planetTypeUrl= BitmapUtil.getPicUrl(String.valueOf(domainInfo.getIcon()),
IshehuiSeoulApplication.screenWidth / 5, BitmapUtil.IMAGE_PNG);
holder.setImageView(R.id.plant_icon,planetTypeUrl,R.drawable.default_head);
int rankStatus = domainInfo.getStatus();
TextView domainSort=holder.getView(R.id.plant_sort_value);
TextView domainRankView=holder.getView(R.id.plant_rank);
switch (rankStatus){
case DomainInfoEx.RANK_UP:
domainSort.setText(String.valueOf(domainInfo.getUpOrdownCount()));
domainSort.setCompoundDrawables(null,null,upDrawable,null);
break;
case DomainInfoEx.RANK_DOWN:
domainSort.setText(String.valueOf(domainInfo.getUpOrdownCount()));
domainSort.setCompoundDrawables(null,null,downDrawable,null);
break;
default:
domainSort.setText("");
domainSort.setCompoundDrawables(null,null,noneDrawable,null);
break;
}
switch (position){
case 0:
domainRankView.setBackgroundResource(R.drawable.strong_user_king);
break;
case 1:
domainRankView.setBackgroundResource(R.drawable.strong_user_silver);
break;
case 2:
domainRankView.setBackgroundResource(R.drawable.strong_user_cop);
break;
default:
domainRankView.setBackgroundResource(R.drawable.rank_txt_bg);
break;
}
int value = position+1;
if(value>99){
domainRankView.setText("...");
}else{
domainRankView.setText(String.valueOf(position+1));
}
setForwardEvent(holder.getConvertView(), domainInfo);
}
});
最后说明下:我写的这个适配器只是初步内容,后续会继续关注大神的对于通用适配器的关注,并且根据自己项目中的实际开发需求继续完善,欢迎大家围观,如果大家有什么好的想法可以继续完善 到时候不要忘记私密我哦,共同学习,共同进步~~~