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 SparseArray<View> sparseArray; 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<View>(); 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,所以这边需要更新position 30 return (easyViewHolder)convertview.getTag(); 31 32 } 33 public <T extends View> 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 easyAdapter<T> extends BaseAdapter { 13 14 private Context context; 15 private ArrayList<T> data; 16 private LayoutInflater inflater; 17 private int LayoutId; 18 easyViewHolder easyholder; 19 public easyAdapter( Context context,ArrayList<T> data,int layoutid) 20 { 21 this.context=context; 22 this.data=data; 23 inflater.from(context); 24 this.LayoutId=layoutid; 25 } 26 @Override 27 public int getCount() { 28 // TODO Auto-generated method stub 29 return data.size(); 30 } 31 32 @Override 33 public Object getItem(int arg0) { 34 // TODO Auto-generated method stub 35 return arg0; 36 } 37 38 @Override 39 public long getItemId(int arg0) { 40 // TODO Auto-generated method stub 41 return arg0; 42 } 43 44 @Override 45 public View getView(int arg0, View arg1, ViewGroup arg2) { 46 // TODO Auto-generated method stub 47 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<User> { 11 12 public MyAdapter(Context context, ArrayList<User> data, int layoutId) { 13 super(context, data, layoutId); 14 // TODO Auto-generated constructor stub 15 } 16 //只需在下面函数传入你所需要的值 17 public void setConverView(easyViewHolder myViewHolder, User t) { 18 // TODO Auto-generated method stub 19 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。