Adapter ViewHolder 封装实践

尝试Android中ViewHolder模式进行封装的实践

提供一个ViewHolder接口,约定其实现类具有一个以View为参数的构造器,构造器中写各种findViewById。接口方法bindItem提供将item显示到View的方法。

对Adapter以及ArrayAdapter作出扩展,简化关于View回收判断部分的代码。

以下为具体实现。

 

package com.zwb.commonlibs.adapters;

/**
 * 为{@link ArrayViewHolderAdapter}及{@link ViewHolderAdapter}提供ViewHolder,
 * 提供从convertView生成ViewHolder的构造器和从item生成视图的方法
 *
 * @author zwb
 */
public interface ViewHolder {

    /**
     * 由item生成视图
     *
     * @param o     传入的item
     * @param position adapter中的位置
     */
    void bindItem(Object o, int position);
}

 

package com.zwb.commonlibs.adapters;

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

import java.lang.reflect.Constructor;

/**
 * 使用{@link ViewHolder}的{@link BaseAdapter}
 */
public abstract class ViewHolderAdapter extends BaseAdapter {
    @Override
    public long getItemId(int position) {
        return position;
    }

    protected abstract int getResId(int viewType);

    protected abstract Class<? extends ViewHolder> getViewHolderClass(int viewType);

    @Override
    public final View getView(int position, View convertView, ViewGroup parent) {
        int viewType = getItemViewType(position);
        if (convertView == null) {
            convertView = LayoutInflater.from(parent.getContext()).inflate(getResId(viewType), parent, false);
            try {
                Constructor<? extends ViewHolder> constructor = getViewHolderClass(viewType).getConstructor(View.class);
                ViewHolder viewHolder = constructor.newInstance(convertView);
                convertView.setTag(viewHolder);
            } catch (Exception e) {
                throw new RuntimeException("ViewHolder必须有一个View参数的构造器");
            }
        }
        //noinspection unchecked
        ViewHolder viewHolder = (ViewHolder) convertView.getTag();
        viewHolder.bindItem(getItem(position), position);
        return convertView;
    }
}

 

 

 

package com.zwb.commonlibs.adapters;

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

import java.lang.reflect.Constructor;
import java.util.List;

/**
 * 使用{@link ViewHolder}的{@link ArrayAdapter}
 *
 * @param <T> 数据类型
 * @author zwb
 */
public class ArrayViewHolderAdapter<T> extends ArrayAdapter<T> {
    protected LayoutInflater mLayoutInflater;
    private int mResource;
    private Constructor<? extends ViewHolder> mConstructor;

    public ArrayViewHolderAdapter(Context context, int resource, Class<? extends ViewHolder> class1) {
        super(context, 0);
        init(context, resource, class1);
    }

    public ArrayViewHolderAdapter(Context context, int resource, List<T> objects, Class<? extends ViewHolder> class1) {
        super(context, 0, objects);
        init(context, resource, class1);
    }

    private void init(Context context, int resource, Class<? extends ViewHolder> clazz) {
        mResource = resource;
        mLayoutInflater = LayoutInflater.from(context);
        try {
            mConstructor = clazz.getConstructor(View.class);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(clazz.getName() + " 必须带有View参数的构造器");
        }
    }

    @Override
    public final View getView(int position, View convert, ViewGroup parent) {
        ViewHolder viewHolder = null;
        if (convert == null) {
            convert = mLayoutInflater.inflate(mResource, parent, false);
            try {
                viewHolder = mConstructor.newInstance(convert);
            } catch (Exception e) {
                e.printStackTrace();
            }
            convert.setTag(viewHolder);
        } else {
            //noinspection unchecked
            viewHolder = (ViewHolder) convert.getTag();
        }
        //noinspection ConstantConditions
        viewHolder.bindItem(getItem(position), position);
        return convert;
    }
}

 

 

以下为两个Demo

 

使用ArrayViewHolderAdapter

 

    public class ViewHolderImpl implements ViewHolder {
        private final TextView name, time, code;

        public ViewHolderImpl(View view) {
            name = (TextView) view.findViewById(R.id.textName);
            time = (TextView) view.findViewById(R.id.textTime);
            code = (TextView) view.findViewById(R.id.textCode);
        }

        @Override
        public void bindItem(Object o, int position) {
            DataObject item = (DataObject) o;
            name.setText(item.getName());
            time.setText(item.getTime());
            code.setText(item.getCode());
        }
    }
//创建Adapter
ArrayAdapter<DataObject> adapter=new ArrayViewHolderAdapter<>(context,R.layout.data_object,ViewHolderImpl.class);

 

使用ViewHolderAdapter

 

public class ViewHolder1 implements ViewHolder{
    //实现同上
}

 

public class ViewHolder2 implements ViewHolder{
    //实现同上
}

 

public class MyAdapter extends ViewHolderAdapter{
    public Object getItem(int position){
        //TODO
}

   public int getItemCount(){
     //TODO
   } public int getViewTypeCount(){ return 2; } public int getItemViewType(int position){ //TODO } public Class<? extends ViewHolder> getViewHolderClass(int viewType){ return viewType==0?ViewHolder1.class:ViewHolder2.class; } public int getResId(int viewType){ return viewType==0?R.layout.item1:R.layout.item2; } }



 

posted @ 2015-10-25 12:49  Dave_Zhu  阅读(336)  评论(0编辑  收藏  举报