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

  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.youkuaiyun.com/detail/xiangxi101/9341641

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值