大家在安卓开发过程中,经常会用到listview或者gridview,在编写代码的时候为了节约资源我们通常会采用持有者模式,即ViewHolder,如果一个工程中有多个listview,通常情况下我会写多个ViewHolder,还有多个adapter,每个adapter都要重写一遍里面的抽象方法,今天就教大家如何避免如此繁重的工作,能够一劳永逸。
首先我们先看一下传统适配器的写法。比如下面这段:
package com.jy.myadapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
/**
* User: juyao(1149950714@qq.com)
* Date: 2015-12-12
* Time: 15:03
*/
public class OriginAdapter extends BaseAdapter{
private List<Bean> list;
private Context mcontext;
private LayoutInflater minflater;
public OriginAdapter(List<Bean> list, Context mcontext) {
this.list = list;
this.mcontext = mcontext;
minflater=LayoutInflater.from(mcontext);
}
@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) {
ViewHolider holder;
if(convertView==null){
holder=new ViewHolider();
convertView=minflater.inflate(R.layout.listitem,parent,false);
holder.title= (TextView) convertView.findViewById(R.id.title);
holder.dec= (TextView) convertView.findViewById(R.id.dec);
holder.time= (TextView) convertView.findViewById(R.id.time);
convertView.setTag(holder);
}else{
holder= (ViewHolider) convertView.getTag();
}
holder.title.setText(list.get(position).getTitlel());
holder.dec.setText(list.get(position).getDec());
holder.time.setText(list.get(position).getTime());
return convertView;
}
class ViewHolider{
TextView title;
TextView dec;
TextView time;
}
}
是不是很熟悉,当我们在开发多个listview的时候,都要对应不同的viewholder,所以我们可以考虑将viewholder封装起来,通过一个容器获取对应的view,提到容器,我们第一反应就是用map来存储键值对,其实在安卓中,还有一个类,叫做
SparseArray
在这个类里面有这么一段介绍,
It is intended to be more memory efficient
* than using a HashMap to map Integers to Objects
大概意思就是说它就相当于是hashmap,但是比hashmao效率更高,但是有一点要注意的是,SparseArray的键只能是integer类型!下面是我封装好了的一个ViewHolder类。
package com.jy.myadapter;
import android.content.Context;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
/**
* User: juyao(1149950714@qq.com)
* Date: 2015-12-12
* Time: 15:38
*/
public class ViewHolder {
private SparseArray<View> mViews;
private int mPosition;
private View mConvertView;
public ViewHolder(Context context,ViewGroup parent,int layoutid,int position){
this.mPosition=position;
this.mViews=new SparseArray<View>();
mConvertView= LayoutInflater.from(context).inflate(layoutid,parent,false);
mConvertView.setTag(this);
}
public static ViewHolder get(Context context,View convertview,ViewGroup parent,int layoutid,int position){
if(convertview==null){
return new ViewHolder( context, parent,layoutid, position);
}else{
ViewHolder holder=(ViewHolder) convertview.getTag();
holder.mPosition=position;
return holder;
}
}
public View getmConvertView() {
return mConvertView;
}
/**
* 根据id寻找控件
* @param viewid
* @return
*/
public <T extends View> T getView(int viewid){
View view=mViews.get(viewid);
if(view==null){
view=mConvertView.findViewById(viewid);
mViews.put(viewid,view);
}
return (T) view;
}
/**
* 为文本赋值
*/
public void setText(int Viewid,String text){
TextView tv=getView(Viewid);
tv.setText(text);
}
}
其其实看这段代码很熟悉,因为他的原理和我们之前写的是一样的,只不过这里进行了封装,仔细看的应该可以看明白。其中settext方法是给Textview进行赋值,当然,类似的,比如imageview等等,都可以在这里面添加对应的方法,我这里是拿Textview举例。封装好了ViewHolder之后,我们来看看怎么使用。下面这段代码就是使用封装好的ViewHolder的情况,主要看getview()方法中,是不是精简了不少?
package com.jy.myadapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import org.w3c.dom.Text;
import java.util.List;
/**
* User: juyao(1149950714@qq.com)
* Date: 2015-12-12
* Time: 15:03
*/
public class MydapterWithCommonViewHolder extends BaseAdapter{
private List<Bean> list;
private Context mcontext;
private LayoutInflater minflater;
public MydapterWithCommonViewHolder(List<Bean> list, Context mcontext) {
this.list = list;
this.mcontext = mcontext;
minflater=LayoutInflater.from(mcontext);
}
@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 holder=ViewHolder.get(mcontext,convertView,parent,R.layout.listitem,position);
holder.setText(R.id.title,list.get(position).getTitlel());
holder.setText(R.id.dec,list.get(position).getDec());
holder.setText(R.id.time,list.get(position).getTime());
return holder.getmConvertView();
}
只需要五行代码。当然,这还不是最简单的,上面我说到,除了viewholder,在多个listview的情况下我们要编写多个adapter,每一个adapter都要重写多个抽象方法,那我们是不是也可以写一个通用的adapter,然后使用的时候继承这一个通用adapter
这样说很难理解,直接看代码,下面是一个通用的adapter
package com.jy.myadapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import java.util.List;
/**
* User: juyao(1149950714@qq.com)
* Date: 2015-12-12
* Time: 16:26
*/
public abstract class CommenAdapter<T> extends BaseAdapter{
protected Context mContext;
protected List<T> mData;
private LayoutInflater mInflater;
private int layoutid;
public CommenAdapter(Context context,List<T> datas,int layoutid) {
this.mContext=context;
this.mData=datas;
this.layoutid=layoutid;
mInflater=LayoutInflater.from(context);
}
@Override
public int getCount() {
return mData.size();
}
@Override
public T getItem(int position) {
return mData.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
ViewHolder holder=ViewHolder.get(mContext,convertView,parent,layoutid,position);
convert(holder,getItem(position));
return holder.getmConvertView();
};
public abstract void convert(ViewHolder holder,T t);
}
其中,conver这个抽象方法就是用来实现每个不同listview的不同处理逻辑,还是拿原来的adapter为例,继承自这个通用adapter,这样就不用重写那一连串方法。继承后的代码如下:
package com.jy.myadapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import org.w3c.dom.Text;
import java.util.List;
/**
* User: juyao(1149950714@qq.com)
* Date: 2015-12-12
* Time: 15:03
*/
public class MydapterWithCommonViewHolder extends CommenAdapter<Bean>{
public MydapterWithCommonViewHolder(List<Bean> data, Context context) {
super(context,data,R.layout.listitem);
}
@Override
public void convert(ViewHolder holder, Bean bean) {
holder.setText(R.id.title,bean.getTitlel());
holder.setText(R.id.dec,bean.getDec());
holder.setText(R.id.time,bean.getTime());
}
}
短短几行代码,就搞定了。
现在我们来对比一下前后的代码差距,一开始用我们通常的写法:
package com.jy.myadapter;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;
import java.util.List;
/**
* User: juyao(1149950714@qq.com)
* Date: 2015-12-12
* Time: 15:03
*/
public class OriginAdapter extends BaseAdapter{
private List<Bean> list;
private Context mcontext;
private LayoutInflater minflater;
public OriginAdapter(List<Bean> list, Context mcontext) {
this.list = list;
this.mcontext = mcontext;
minflater=LayoutInflater.from(mcontext);
}
@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) {
ViewHolider holder;
if(convertView==null){
holder=new ViewHolider();
convertView=minflater.inflate(R.layout.listitem,parent,false);
holder.title= (TextView) convertView.findViewById(R.id.title);
holder.dec= (TextView) convertView.findViewById(R.id.dec);
holder.time= (TextView) convertView.findViewById(R.id.time);
convertView.setTag(holder);
}else{
holder= (ViewHolider) convertView.getTag();
}
holder.title.setText(list.get(position).getTitlel());
holder.dec.setText(list.get(position).getDec());
holder.time.setText(list.get(position).getTime());
return convertView;
}
class ViewHolider{
TextView title;
TextView dec;
TextView time;
}
}
再看最后我们封装好的写法:
package com.jy.myadapter;
import android.content.Context;
import java.util.List;
/**
* User: juyao(1149950714@qq.com)
* Date: 2015-12-12
* Time: 15:03
*/
public class MydapterWithCommonViewHolder extends CommenAdapter<Bean> {
public MydapterWithCommonViewHolder(List<Bean> data, Context context) {
super(context, data, R.layout.listitem);
}
@Override
public void convert(ViewHolder holder, Bean bean) {
holder.setText(R.id.title, bean.getTitlel());
holder.setText(R.id.dec, bean.getDec());
holder.setText(R.id.time, bean.getTime());
}
}
是不是简单了很多!!!