ListView、GridView等等非常多的东西都需要适配器。而如果开发一个app每一个listview都有写一个Adapter的话,那还怎么愉快的玩游戏。。
什么是ViewHolider以及的用法和为什么要用?
这位博主写的非常好。
http://www.cnblogs.com/lichenwei/p/4085107.html
所谓的万能适配器,无非是将适配器的重复代码抽取出来进行封装。不同功能的代码则留写一个方法留给用户复写,则每个listview的适配器就只变成几句话就够了。
这是一般适配器的代码:
private class MyAdapter extends BaseAdapter { private Context mcontext=null; private LayoutInflater inflater; public MyAdapter(Context c) { this.mcontext=c; this.inflater=LayoutInflater.from(c);//from告诉系统从哪里获得布局填充器 } @Override public int getCount() { // TODO Auto-generated method stub return mListTitle.length; } @Override public Object getItem(int arg0) { // TODO Auto-generated method stub return arg0; } @Override public long getItemId(int arg0) { // TODO Auto-generated method stub return arg0; } @Override public View getView(int arg0, View arg1, ViewGroup arg2) { // TODO Auto-generated method stub ViewHolder viewholder =null; if (arg1==null) { viewholder=new ViewHolder(); arg1=inflater.inflate(R.layout.iconlist, arg2, false); viewholder.iv=(ImageView)arg1.findViewById(R.id.imageview); viewholder.title=(TextView)arg1.findViewById(R.id.title); viewholder.text=(TextView)arg1.findViewById(R.id.text); arg1.setTag(viewholder); } else { viewholder=(ViewHolder)arg1.getTag(); } viewholder.iv.setImageResource(R.drawable.icon1); viewholder.title.setText(mListTitle[arg0]); viewholder.text.setText(mListStr[arg0]); return arg1; } } private class ViewHolder { private ImageView iv=null; private TextView title=null; private TextView text=null; }
首先我们先对ViewHolder进行封装:
1、ViewHolder将xml文件转换成convertview,并将转换后的view返回
2、要设置标签
3、判断convertview是否为空,空的话重新new创建,不为空的话getTag();
代码:
1 package com.example.list_view; 2 import android.content.Context; 3 import android.util.SparseArray; 4 import android.view.LayoutInflater; 5 import android.view.View; 6 import android.view.ViewGroup; 7 8 public class easyViewHolder { 9 10 private SparseArraysparseArray;11 private Context context;12 private int LayoutId;13 private View convertview;14 public easyViewHolder(Context mcontext,View mconvertview,int LayoutId,ViewGroup parent)15 {16 this.context=mcontext;17 this.sparseArray=new SparseArray ();18 this.convertview=LayoutInflater.from(mcontext).inflate(LayoutId, parent, false);19 convertview.setTag(this); 20 }21 public static easyViewHolder get(Context context,View convertview,int LayoutId,ViewGroup parent)22 {23 if (convertview==null)24 {25 return new easyViewHolder(context, convertview, LayoutId, parent);26 }27 28 29 // 特别需要注意的一点,由于ListView的复用,比如屏幕只显示5个Item,那么当下拉到第6个时会复用第1个的Item,所以这边需要更新position30 return (easyViewHolder)convertview.getTag();31 32 }33 public T getView(int viewId)//通过id找到组件34 {35 View view = sparseArray.get(viewId);36 if (view==null)37 {38 view=(View)this.convertview.findViewById(viewId);39 sparseArray.put(viewId, view);40 }41 return (T)view;42 43 }44 public View getConvertView()45 {46 return this.convertview;47 }48 }
再封装一个适配器:
声明一个抽象类
1、保留不变的方法
2、修改getview()
3、写一个需要重写函数用来给用户传值。
1 package com.example.list_view; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.content.Context; 7 import android.view.LayoutInflater; 8 import android.view.View; 9 import android.view.ViewGroup;10 import android.widget.BaseAdapter;11 12 public abstract class easyAdapterextends BaseAdapter {13 14 private Context context;15 private ArrayList data;16 private LayoutInflater inflater;17 private int LayoutId;18 easyViewHolder easyholder;19 public easyAdapter( Context context,ArrayList data,int layoutid)20 {21 this.context=context;22 this.data=data;23 inflater.from(context);24 this.LayoutId=layoutid;25 }26 @Override27 public int getCount() {28 // TODO Auto-generated method stub29 return data.size();30 }31 32 @Override33 public Object getItem(int arg0) {34 // TODO Auto-generated method stub35 return arg0;36 }37 38 @Override39 public long getItemId(int arg0) {40 // TODO Auto-generated method stub41 return arg0;42 }43 44 @Override45 public View getView(int arg0, View arg1, ViewGroup arg2) {46 // TODO Auto-generated method stub47 final easyViewHolder easyholder=getHolder(context, arg1, LayoutId, arg2);48 setConverView(easyholder,data.get(arg0));//需要用户复写传值49 return easyholder.getConvertView();50 }51 public abstract void setConverView(easyViewHolder easyViewHolder, T t);52 public static easyViewHolder getHolder(Context context,View convertview,int LayoutId,ViewGroup parent)53 {54 return easyViewHolder.get(context, convertview, LayoutId, parent);55 }56 }
以上的两个类除了添加新功能不用在对其改变。
接下来我们就可以以最少的代码完成适配器:
1 package com.example.list_view; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import android.content.Context; 7 import android.widget.ImageView; 8 import android.widget.TextView; 9 10 public class MyAdapter extends easyAdapter{11 12 public MyAdapter(Context context, ArrayList data, int layoutId) {13 super(context, data, layoutId);14 // TODO Auto-generated constructor stub15 }16 //只需在下面函数传入你所需要的值17 public void setConverView(easyViewHolder myViewHolder, User t) {18 // TODO Auto-generated method stub19 20 ((ImageView)myViewHolder.getView(R.id.imageview)).setImageResource(R.drawable.icon1);21 ((TextView)myViewHolder.getView(R.id.title)).setText(t.getTitle());22 ((TextView)myViewHolder.getView(R.id.text)).setText(t.getText());23 24 }25 26 }
MainActivity的代码:
for (int i=0;i<10;i++)
{ User user=new User(); user.setIv(R.drawable.icon1); user.setTitle("用户"+i); user.setText("1000"+i); list.add(user); } MyAdapter adapter=new MyAdapter(MainActivity.this, list, R.layout.iconlist); list1.setAdapter(adapter);只是单纯传入你这个listview所需要的数据源,以及传入listview的布局,便可完成各式各样的listview。