您的位置:首页 > 移动开发 > Android开发

Android之listview万能适配器

2016-07-10 10:46 507 查看
什么叫万能适配器,其实就是这种适配器是万能的,所有需要使用适配器的组件,都可用这一个适配器就行。

既然这样,就来讲讲吧。

先来看看效果图:



当然了,这只是很简单的例子,很简单的布局,这里只是用来做个例子,以后也可以写别的布局,这个适配器都是适用的~

那我们就来讲讲怎么从普通的适配器到万能适配器的吧~

步骤:

1.首先普通的适配器的写法是--MyAdapter.class:

public class MyAdapter extends BaseAdapter{

private Context context;
private List<Bean>datas;
LayoutInflater layoutInflater;
int resId;//布局文件

public MyAdapter(Context context, List<Bean> datas,int resId) {
this.context = context;
this.datas = datas;
this.resId=resId;
layoutInflater=LayoutInflater.from(context);
}

@Override
public int getCount() {
// TODO Auto-generated method stub
return datas.size();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return datas.get(position);
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
if(convertView==null){
convertView=layoutInflater.inflate(R.layout.listview,null);
holder=new ViewHolder();
holder.title=(TextView) convertView.findViewById(R.id.title);
holder.desc=(TextView) convertView.findViewById(R.id.desc);
holder.time=(TextView) convertView.findViewById(R.id.time);
holder.phone=(TextView) convertView.findViewById(R.id.phone);
convertView.setTag(holder);
}else{
holder=(ViewHolder) convertView.getTag();
}
holder.title.setText(datas.get(position).getTitle());
holder.desc.setText(datas.get(position).getDesc());
holder.time.setText(datas.get(position).getTime());
holder.phone.setText(datas.get(position).getPhone());
}
static class ViewHolder{
TextView title,time,desc,phone;
}
}
2.万能适配器的编写步骤:

(1)首先我们得分析哪些代码是不变的,哪些是可变的,这样才能确定哪些代码能够减少。

这三个重写的方法应该是不变的。

@Override
public int getCount() {
// TODO Auto-generated method stub
return datas.size();
}

@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return datas.get(position);
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
还有getView方法里面的一些代码:

if(convertView==null){
convertView=layoutInflater.inflate(R.layout.listview,null);
holder=new ViewHolder();
holder.title=(TextView) convertView.findViewById(R.id.title);
holder.desc=(TextView) convertView.findViewById(R.id.desc);
holder.time=(TextView) convertView.findViewById(R.id.time);
holder.phone=(TextView) convertView.findViewById(R.id.phone);
convertView.setTag(holder);
}else{
holder=(ViewHolder) convertView.getTag();
}


只不过findViewById我们需要处理一下。所以我们应该把这些不变的代码抽取出来,不应该让用户重复写这些代码。

把这些代码抽取出来,当然这些代码都应该放在ViewHolder中

(2)新建一个类 ViewHolder.java

public class ViewHolder {
private View convertView,int mposition;
//构造函数
//每个convertView会绑定一个ViewHolder对象
public ViewHolder(Context context, int mposition,View convertView,ViewGroup parent,int resId) {
convertView=View.inflate(context, resId, null);
this.convertView=convertView;this.mposition=mposition;
convertView.setTag(this);
}
//拿到一个ViewHolder对象
public static ViewHolder get(Context context,int mposition,
View convertView,ViewGroup parent,int resId){

if(convertView==null){
return new ViewHolder(context,mposition,convertView, parent, resId);
}else {
ViewHolder holder=(ViewHolder) convertView.getTag();
return holder;
}
}
}
传过来的参数包括:Context context, int mposition

,View convertView, ViewGroup parent, int layoutId,这些参数都是加载布局文件所需要的。

然后就是这些代码需要抽取了:

holder.title=(TextView) convertView.findViewById(R.id.title);
holder.desc=(TextView) convertView.findViewById(R.id.desc);
holder.time=(TextView) convertView.findViewById(R.id.time);
holder.phone=(TextView) convertView.findViewById(R.id.phone);
在类ViewHolder中新建方法:

//泛型,返回的是View的一个子类
//获取控件,通过控件的ID获取对应的控件,如果没有就加入mViews
//resId是一个ID
public <T extends View>T getView(int resId){
View view=mViews.get(resId);
if(view==null){
//如果mViews没有相应的控件,我们就从convertView中找到这个控件,
//并将这个控件和其ID存放在mViews
view=convertView.findViewById(resId);
mViews.put(resId, view);
}
return (T) view;
}
接下来要在ViewHolder这个类的返回convertView,这个返回值就容易了,直接返回就行了

//返回一个convertView对象
public View getmConvertView() {
return convertView;
}


然后在MyAdapter中getView方法代码如下:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
//2.
ViewHolder holder=ViewHolder.get(context, position, convertView,
parent, resId);
((TextView)holder.getView(R.id.title)).setText(datas.get(position).getTitle());
((TextView)holder.getView(R.id.desc)).setText(datas.get(position).getDesc());
((TextView)holder.getView(R.id.time)).setText(datas.get(position).getTime());
((TextView)holder.getView(R.id.phone)).setText(datas.get(position).getPhone());
return holder.getmConvertView();
}


这部分工作都完了,就只留下了为组件设置数据的那段代码了,这段代码由于是可变的,应该让用户来做,所以设置为抽象方法。

(3)新建一个类 CommonAdapter.java 继承BaseAdapter:

//(把MyAdapter中的getView方法抽取出来)
public abstract class CommonAdapter<T> extends BaseAdapter{

private Context context;
private List<T>data;//data是不明类型的数据
int resId;//布局文件
public CommonAdapter(Context context,List<T>data,int resId){
this.context=context;
this.resId=resId;
this.data=data;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return data.size();
}

//通过查看源代码发现,getItem方法不是在Baseadapter类中被调用的,而是在Adapterview中被调用的。
@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return data.get(position);
}

@Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}

@Override
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder=ViewHolder.get(context, position, convertView, parent, resId);
current(holder,getItem(position));//把那个getView方法抽取出来
return holder.getmConvertView();
}
public abstract void current(ViewHolder holder,Object object);
}
然后有这些代码还不行~还要实现那个抽象方法~

所以新建一个 Adapter 继承 CommonAdapter-MagicAdapter:

public class MagicAdapter extends CommonAdapter<Bean>{

//resId是布局文件,调用基类的构造方法
public MagicAdapter(Context context, List<Bean> data, int resId) {
super(context, data, resId);
// TODO Auto-generated constructor stub
}

@Override
public void current(ViewHolder holder, Object object) {
// TODO Auto-generated method stub
Bean bean=(Bean)object;
((TextView)holder.getView(R.id.title)).setText(bean.getTitle());
((TextView)holder.getView(R.id.desc)).setText(bean.getDesc());
((TextView)holder.getView(R.id.phone)).setText(bean.getPhone());
((TextView)holder.getView(R.id.time)).setText(bean.getTime());
}

}
然后在MainActivity为listview加载适配器

listview.setAdapter(new MagicAdapter(MainActivity.this, datas,R.layout.listview));
核心代码如下:

MainActivity:

public class MainActivity extends Activity {
private ListView listview;
private List<Bean>datas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();

}
//初始化数据
public void initData() {
// TODO Auto-generated method stub
datas=new ArrayList<Bean>();
for(int i=1;i<10;i++){
Bean bean=new Bean("Android新技能"+i, "Android打造万能适配器", "2016-5-20", "10086");
datas.add(bean);
}
}
//初始化控件
public void initView() {
// TODO Auto-generated method stub
listview=(ListView) findViewById(R.id.listview);
//1.
//listview.setAdapter(new MyAdapter(MainActivity.this, datas));
//2.调用这个适配器,把数据加载出来
listview.setAdapter(new MagicAdapter(MainActivity.this, datas,R.layout.listview));
}

}
Bean:

public class Bean {

String title,desc,time,phone;

public Bean(String title, String desc, String time, String phone) {
super();
this.title = title;
this.desc = desc;
this.time = time;
this.phone = phone;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public String getDesc() {
return desc;
}

public void setDesc(String desc) {
this.desc = desc;
}

public String getTime() {
return time;
}

public void setTime(String time) {
this.time = time;
}

public String getPhone() {
return phone;
}

public void setPhone(String phone) {
this.phone = phone;
}
}
源码:下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息