android 设计模式之Listview不同类型Item利用工厂模式的复用

来源:互联网 发布:网络神兽 编辑:程序博客网 时间:2024/06/05 00:35
  1. 设计思路
    listview需要设计不同的item类型的时,考虑到以后item类型的扩展,还有不同类型item的复用,使用工厂模式,抽象item公共实现接口实现。
    优点:可扩展性强,代码复用度高,执行效率高,复用了convertView和ViewHolder
  2. 具体实现

    demo示例

    1),大体的思路是:给listview设置适配器,自定义一个适配器,这个适配器要实现getViewTypeCount和getItemViewType方法(getViewTypeCount返回值的大小一定要比type数值大,不然报数组越界异常),重点在getView方法返回的每个item的view(convertView),这里就用到工厂模式。
    2),写一个工厂类,里面有个SparseArray<>集合,存放item的convertView,保证复用。再写一个getCreatorByViewType方法,根据不同的type生产不同的item对象。
    3),为了复用和代码简洁,将每个item抽象出来View createView(int position, Object
    data,View convertView, ViewGroup parent),—–MyBaseViewHolder
    createViewHolder(),—-void init(Activity ctx, int
    layoutResId)这三个方法,然后写一个抽象类实现其中的init(将context和布局的id传递过来)和createView(实现复用和蹦出布局)方法。
    4),每个item的类,要实现createViewHolder方法,还有自己的holder类实现公共接口

总体设计类图
总体设计类图
activity里面进行所有数据的初始化,实例化adapter和factory类,将myDataManager,myFactory作为参数传递给adapter

private void initData() {        myDataManager = new MyDataManager();        myDataManager.initData();        myFactory = new MyFactory();        myAdapter = new MyAdapter(this, myDataManager, myFactory);        listView.setAdapter(myAdapter);    }

适配器抽象出getview不同的操作,而这个viewholder类的复用封装给factory完成

public class MyAdapter extends BaseAdapter{    private Activity ctx;    private MyDataManager dataManager;    private MyFactory factory;    public MyAdapter(Activity ctx, MyDataManager dataManager, MyFactory factory) {        this.ctx=ctx;        this.dataManager=dataManager;        this.factory=factory;    }    @Override    public int getCount() {        return dataManager.dataList.size();    }    @Override    public Object getItem(int position) {        return dataManager.dataList.get(position);    }    @Override    public long getItemId(int position) {        return position;    }    /* (non-Javadoc)     * @see android.widget.BaseAdapter#getViewTypeCount()     * 返回总共type的总数     */    @Override    public int getViewTypeCount() {        return MyEntities.VIEWTYPE_ALL;    }    /* (non-Javadoc)     * @see android.widget.BaseAdapter#getItemViewType(int)     * 返回每个item的type     */    @Override    public int getItemViewType(int position) {        return dataManager.viewTypeAllList.get(position);    }    /* (non-Javadoc)     * @see android.widget.Adapter#getView(int, android.view.View, android.view.ViewGroup)     * 返回每一个item的对象     */    @Override    public View getView(int position, View convertView, ViewGroup parent) {        return factory.getCreatorByViewType(ctx, dataManager.viewTypeAllList.get(position), dataManager)                .createView(position, dataManager.dataList.get(position), convertView, parent);    }}

factory类完成每个item的复用,采用SparseArray集合存储,根据datamanager不同的item类型的数据分配对应的item对象

private SparseArray<IMyCrator> mCreators = new SparseArray<IMyCrator>();    public IMyCrator getCreatorByViewType(Activity ctx, int viewType, MyDataManager dataManager) {        IMyCrator creator = mCreators.get(viewType);        if (creator != null) {            return creator;        }        switch (viewType) {        case MyEntities.VIEW_CRATPR1:            creator = new Crator1(ctx, dataManager);            break;        case MyEntities.VIEW_CRATOR2:            creator = new Crator2(ctx, dataManager);            break;        case MyEntities.VIEW_CRATOR3:            creator = new Crator3(ctx, dataManager);            break;        }        mCreators.put(viewType, creator);        return creator;    }

而最终实现不同的item的布局,就要用不同的Crator对象,为了以后item类型的扩展,给这个item抽象出不同的接口,和抽象类,子类只需要实现在getview里面不同的inflate布局和在布局上填充的内容的操作。具体的实现下载源码(付最后)

@Override    public MyBaseViewHolder createViewHolder() {        return new Holder1();    }    class Holder1 extends MyBaseViewHolder{        private TextView name;        private TextView type;        /* (non-Javadoc)         * @see com.song.testfactoryproductitem.MyBaseViewHolder#findViews(android.view.View)         *          */        @Override        public void findViews(View convertView) {            name = (TextView) convertView.findViewById(R.id.name);            type = (TextView) convertView.findViewById(R.id.type);        }        /* (non-Javadoc)         * @see com.song.testfactoryproductitem.MyBaseViewHolder#setData(java.lang.Object, android.view.View, int)         * 给holder设置数据         */        @Override        public void setData(Object data, View convertView, int position) {            if (!(data instanceof Entry2)) {                return;            }            Entry2 e=(Entry2)data;            name.setText(e.getName());            type.setText(e.getType());        }    }//AbsMyCrator类实现private Activity ctx;    private int layoutResId;    /* (non-Javadoc)     * @see com.song.testfactoryproductitem.IMyCrator#createView(int, java.lang.Object, android.view.View, android.view.ViewGroup)     * 初始化每个item的convertView     */    @Override    public View createView(int position, Object data, View convertView, ViewGroup parent) {        MyBaseViewHolder holder = null;        if (convertView == null) {            holder = createViewHolder();            convertView = LayoutInflater.from(ctx).inflate(layoutResId, parent, false);            holder.findViews(convertView);            convertView.setTag(holder);        } else {            holder = (MyBaseViewHolder) convertView.getTag();        }        holder.setData(data, convertView, position);        convertView.setId(position);        return convertView;    }    @Override    public void init(Activity ctx, int layoutResId) {        this.ctx=ctx;        this.layoutResId=layoutResId;    }

有什么不清晰的欢迎留言
付源码http://download.csdn.net/detail/xiangxi101/9341641

/**
* --------------
* 欢迎转载 | 转载请注明
* --------------
* 如果对你有帮助,请点击|顶|
* --------------
* 请保持谦逊 | 你会走的更远
* --------------
* @author css
* @github https://github.com/songsongbrother
* @blog http://blog.csdn.net/xiangxi101
*/

3 0