您的位置:首页 > 编程语言 > PHP开发

ViewHolder baseadatper封装的万能适配器

2016-03-08 12:31 686 查看
再次声明:参考了鸿翔在慕课中的视频,这是视频地址,有兴趣的去看看http://www.imooc.com/learn/372

说一下我的理解:经过这种封装后的适配器,有非常高的复用性,会在开发中节省大量的时间和代码量;另外,最让我值得学习的是,这种封装的思想,在代码中如果一段代码,有重复利用的地方,则应该进行封装。还有就是,越来越感觉到设计模式的重要性。。。。

1:写一个独立的ViewHolder类,和传统的ViewHolder内部类一样,防止控件的反复加载

/**
* 封装的ViewHolder类
* @author Administrator
*
*/
public class listview_ViewHolder {


2:这个类中的核心方法就是一个构造函数和一个对外公布方法

public class listview_ViewHolder {

private LayoutInflater inflater;
private int position;
//integer类型的key,运行速度比较快
private SparseArray<View> lists;

private listview_ViewHolder holder;
private View contenView;
private listview_ViewHolder(Context context ,ViewGroup parent ,int layoutId,int position)
{
lists=new SparseArray<View>();

contenView=LayoutInflater.from(context).inflate(layoutId, parent,false);
contenView.setTag(this);
}
/**
* 对外公布的方法,相当于传统Getview()方法中,viewholder和contentview设置tag
* @param context
* @param position
* @param contentView
* @param parent
* @param layoutID
* @return
*/
public static listview_ViewHolder getInstance(Context context,int position,View contentView,ViewGroup parent,int layoutID)

{
if(contentView==null)
{
return new listview_ViewHolder(context, parent, layoutID, position);
}else{
listview_ViewHolder tag = (listview_ViewHolder) contentView.getTag();
//position不能重复使用
tag.position=position;
return tag;
}
}

注:外部调用getinstance方法,如果contentview为null,怎就会走到构造函数中,构造函数中写了初始化的数据,如果不是null,则从tag中获取,这里的position要赋值一下,防止position重用,造成界面混乱。

3:封装自己的baseadapter
/**
* 封装好的父类适配器,
* 跟封装好viewholder结合使用
* @author Administrator
*
* @param <E>
*/
public abstract class  myBaseAdatper<E> extends BaseAdapter {

注:这里是泛型E,一定是泛型,因为每一个listview或者gridview,都有自己的bean(实体类),不能写死

4:这个类中的和新方法是:

@Override
public View getView(int arg0, View arg1, ViewGroup arg2) {
// TODO Auto-generated method stub
listview_ViewHolder viewHolder=listview_ViewHolder.getInstance(context, arg0, arg1, arg2, layoutId);
//调用一下方法,吧参数传出去
myGetView(viewHolder, getItem(arg0));
return viewHolder.getContenView();
}

public abstract void myGetView(listview_ViewHolder viewHolder,E e);

注:写一个抽象方法,子类必须去实现,同时把viewholder类,和泛型的实体类对象传递出去

5:子类继承自己的父类适配器

public class holderAdatper extends myBaseAdatper<mainlist_mode>{

/**
* 这个构造函数必须要有,因为继承父类的构造函数,其中的初始化参数要拿到这个子类中,
* 不然就会包错误
*
*
* 当调用适配器的时候,就会把参数传到父类适配器中,然后就可以给到viewHolder中
* @param lists
* @param context
* @param layoutId
*/
public holderAdatper(List<mainlist_mode> lists, Context context,
int layoutId) {
super(lists, context, layoutId);
// TODO Auto-generated constructor stub
}

@Override
public void myGetView(listview_ViewHolder viewHolder, final mainlist_mode e) {

viewHolder.SetTextView(R.id.id_item_aire, e.getAire());
viewHolder.SetTextView(R.id.id_item_diqu, e.getDiqu());
viewHolder.SetTextView(R.id.id_item_name, e.getName());
viewHolder.SetTextView(R.id.id_item_number, e.getNumber());

final CheckBox cb=viewHolder.mFindViewById(R.id.id_item_ck);
//checkbox,设置是否选中,设置的事实体类中的值,而不是点击之后的值
cb.setChecked(e.isChecked());
//checkbox的点击事件中,吧点击的值给实体类
cb.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
e.setChecked(cb.isChecked());
}
});

}

}


注:就只有上边一个方法和一个构造函数,这个构造函数一定要有。这样的话,完全可以写成内部类,不过Dome毕竟没有这个复杂的控件和逻辑,所以在实际开发中,还要根据具体情况分析;

另外,对于checkbox混乱问题,上边的代码就是,一定要在bean实体类中,写一个boolean来记录选中状态。





下面是viewholder类中的完整代码:

package com.ljg.cewanneng.app.ViewHolder;

import android.content.Context;
import android.graphics.Bitmap;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

/** * 封装的ViewHolder类 * @author Administrator * */ public class listview_ViewHolder {
private LayoutInflater inflater;
private int position;
//integer类型的key,运行速度比较快
private SparseArray<View> lists;

private listview_ViewHolder holder;
private View contenView;
private listview_ViewHolder(Context context ,ViewGroup parent ,int layoutId,int position)
{
lists=new SparseArray<View>();

contenView=LayoutInflater.from(context).inflate(layoutId, parent,false);
contenView.setTag(this);
}
/**
* 对外公布的方法,相当于传统Getview()方法中,viewholder和contentview设置tag
* @param context
* @param position
* @param contentView
* @param parent
* @param layoutID
* @return
*/
public static listview_ViewHolder getInstance(Context context,int position,View contentView,ViewGroup parent,int layoutID)

{
if(contentView==null)
{
return new listview_ViewHolder(context, parent, layoutID, position);
}else{
listview_ViewHolder tag = (listview_ViewHolder) contentView.getTag();
//position不能重复使用
tag.position=position;
return tag;
}
}
/**
* 在这个viewholder中对contenview进行layoutinflater进行绑定的
* 所以baseAdatper的getview()方法中的返回值用这里的contentview;
* @return
*/
public View getContenView() {
return contenView;
}
/**
* 所有空间的绑定Id的方法,用SparseArray对绑定过的View进行保存
* @param ViewId
* @return
*/
public <T extends View> T mFindViewById(int ViewId)
{
View v=lists.get(ViewId);
if(v==null)
{
v=contenView.findViewById(ViewId);
lists.put(ViewId, v);
}
return (T) v;
}

/**
* 给TextView类型的的控件赋值
* @param ViewId
* @param str
*/
public listview_ViewHolder SetTextView(int ViewId,String str){
//调用getview方法,绑定了所有控件的ID
TextView tv=mFindViewById(ViewId);
tv.setText(str);

return this;
}
/**
* 还可以写设置imageview的方法
*/

public void setImageView(int ViewId,Bitmap bitmap)
{
ImageView im=mFindViewById(ViewId);
im.setImageBitmap(bitmap);
}

}


自己的baseadapter中的完整代码:

package com.ljg.cewanneng.app.ViewHolder;

import java.util.ArrayList;
import java.util.List;

import com.ljg.cewanneng.app.ViewHolder.listview_ViewHolder;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;

/** * 封装好的父类适配器, * 跟封装好viewholder结合使用 * @author Administrator * * @param <E> */ public abstract class myBaseAdatper<E> extends BaseAdapter {
protected LayoutInflater inflater;
protected List<E> lists=new ArrayList<E>();
protected Context context;
private int layoutId;

public myBaseAdatper( List<E> lists,
Context context, int layoutId) {
super();
this.lists = lists;

this.context = context;
this.layoutId = layoutId;
inflater=LayoutInflater.from(context);
}

/**
* 不传递集合数据的构造函数
* @param context
* @param layoutId
*/

public myBaseAdatper(Context context, int layoutId) {
super();
this.context = context;
this.layoutId = layoutId;
inflater=LayoutInflater.from(context);
}

/**
* 删除所有数据方法
* @param list
*/
public void RemoveAllLists(List<E> list){
lists.removeAll(list);
notifyDataSetChanged();
}

/**
* 删除数据的方法
* @param e
*/
public void removeList(E e)
{
lists.remove(e);
notifyDataSetChanged();
}

/**
* 更新数据到头不的方法
* @param e
*/
public void AddTopList(E e)
{
lists.add(0, e);
notifyDataSetChanged();
}

/**
* 刷新适配器的方法
*/
public void NotifyDataSetChanged()
{
this.NotifyDataSetChanged();
}

/**
* 一次添加多条数据
* @param list
*/
public void Addlists(List<E> list)
{
lists.addAll(list);
notifyDataSetChanged();
}

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

@Override
public E getItem(int arg0) {
// TODO Auto-generated method stub
return lists.get(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
listview_ViewHolder viewHolder=listview_ViewHolder.getInstance(context, arg0, arg1, arg2, layoutId);
//调用一下方法,吧参数传出去
myGetView(viewHolder, getItem(arg0));
return viewHolder.getContenView();
}

public abstract void myGetView(listview_ViewHolder viewHolder,E e);

}


注:里边有一些更新数据的方法,因为不同的项目,有不同的需求,不一定要在构造函数中传递数据。总之这里还有诸多没有加入的方法,因为当用的地方不一样,就会逐步的去完善。。。。

下面是Dome下载的地址:
http://download.csdn.net/detail/jiajia1112223/9455334
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: