美文网首页
装饰者设计模式-RecyclerView添加头部和底部

装饰者设计模式-RecyclerView添加头部和底部

作者: _风听雨声 | 来源:发表于2020-04-09 11:48 被阅读0次

引言

装饰者设计模式,装饰者设计模式在Android系统源码中也能经常见到,如IO流、ContextWrapper,ListView的addHeaderView和addFooterView...等等,这些都是装饰者设计模式运用的直观体现。


装饰者模式的概念

装饰者模式又名包装(Wrapper)模式。装饰者模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案。

装饰者模式动态地将责任附加到对象身上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。


装饰者模式的实例-RecyclerView添加头部和底部实例

RecyclerView是谷歌推出的ListView的替代方案,但是谷歌并没有帮我们去实现RecyclerView的添加头部和底部。ListView是谷歌实现了添加头部和底部,ListView是使用装饰者设计模式实现的。那么,如果我们要使用装饰者设计模式去实现RecyclerView的添加头部和底部要怎么实现呢?

实现思路

1.在WrapRecyclerViewAdapter构造方法将原来的adapter传入进来
2.创建添加头部和底部的方法
3.getItemCount()方法返回原来的item数量加上添加进来的HeadView和FooterView数量。
4.在onCreateViewHolder() onBindViewHolder()根据position来判断当前是headView还是原adapter的itemView或者footerView,根据对应的数量,做相应的处理
5.新建WrapRecyclerView继承自RecyclerView,实现添加头部和底部的方法
6.注册AdapterDataObserver观察者将两个Adapter关联

public class WrapRecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
    private List<View> headerViews;
    private List<View> footerViews;
    private RecyclerView.Adapter mAdapter;

    public WrapRecyclerViewAdapter(@NonNull RecyclerView.Adapter adapter) {
        this.mAdapter = adapter;
        headerViews = new ArrayList<>();
        footerViews = new ArrayList<>();
    }

    @NonNull
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int position) {
        int headViewCount = headerViews.size();
        if (position < headViewCount) {
            return createHeaderFooterHolderView(headerViews.get(position));
        }
        int justPosition = mAdapter.getItemCount() + headViewCount;
        if (position < justPosition) {
            return mAdapter.onCreateViewHolder(parent, mAdapter.getItemViewType(position));
        }

        return createHeaderFooterHolderView(footerViews.get(position - justPosition));
    }

    @Override
    public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
        int headViewCount = headerViews.size();
        if (position < headViewCount) {
            return;
        }
        int justPosition = mAdapter.getItemCount() + headViewCount;
        if (position < justPosition) {
            mAdapter.onBindViewHolder(holder, position - headViewCount);
            return;
        }
    }

    @Override
    public int getItemCount() {
        return mAdapter.getItemCount() + headerViews.size() + footerViews.size();
    }

    @Override
    public int getItemViewType(int position) {
        return position;
    }

    private RecyclerView.ViewHolder createHeaderFooterHolderView(View view) {
        return new RecyclerView.ViewHolder(view) {
        };
    }

    public void addHeaderView(View view) {
        if (!headerViews.contains(view)) {
            headerViews.add(view);
            notifyDataSetChanged();
        }
    }

    public void addFooterView(View view) {
        if (!footerViews.contains(view)) {
            footerViews.add(view);
            notifyDataSetChanged();
        }
    }

    public void removeHeaderView(View view) {
        if (headerViews.contains(view)) {
            headerViews.remove(view);
            notifyDataSetChanged();
        }
    }

    public void removeFooterView(View view) {
        if (footerViews.contains(view)) {
            footerViews.remove(view);
            notifyDataSetChanged();
        }
    }
}
public class WrapRecyclerView extends RecyclerView {
    private Adapter mAdapter;
    private WrapRecyclerViewAdapter mWrapAdapter;

    public WrapRecyclerView(@NonNull Context context) {
        this(context, null);
    }

    public WrapRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public WrapRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public void setAdapter(@Nullable Adapter adapter) {
        if (adapter != null) {
            this.mAdapter = adapter;
            mWrapAdapter = new WrapRecyclerViewAdapter(adapter);
            registerObserver();
        }
        super.setAdapter(mWrapAdapter);
    }

    private void registerObserver() {
        mAdapter.registerAdapterDataObserver(new AdapterDataObserver() {
            @Override
            public void onChanged() {
                super.onChanged();
                mWrapAdapter.notifyDataSetChanged();
            }
        });
    }

    public void addHeaderView(View view) {
        if (mWrapAdapter != null) {
            mWrapAdapter.addHeaderView(view);
        }
    }

    public void addFooterView(View view) {
        if (mWrapAdapter != null) {
            mWrapAdapter.addFooterView(view);
        }
    }

    public void removeHeaderView(View view) {
        if (mWrapAdapter != null) {
            mWrapAdapter.removeHeaderView(view);
        }
    }

    public void removeFooterView(View view) {
        if (mWrapAdapter != null) {
            mWrapAdapter.removeFooterView(view);
        }
    }
}

装饰者模式的优缺点

装饰模式的优点

(1)装饰模式与继承关系的目的都是要扩展对象的功能,但是装饰模式可以提供比继承更多的灵活性。装饰模式允许系统动态决定“贴上”一个需要的“装饰”,或者除掉一个不需要的“装饰”。继承关系则不同,继承关系是静态的,它在系统运行前就决定了。

(2)通过使用不同的具体装饰类以及这些装饰类的排列组合,设计师可以创造出很多不同行为的组合。

装饰模式的缺点

由于使用装饰模式,可以比使用继承关系需要较少数目的类。使用较少的类,当然使设计比较易于进行。但是,在另一方面,使用装饰模式会产生比使用继承关系更多的对象。更多的对象会使得查错变得困难,特别是这些对象看上去都很相像。

相关文章

网友评论

      本文标题:装饰者设计模式-RecyclerView添加头部和底部

      本文链接:https://www.haomeiwen.com/subject/qhnqmhtx.html