Android设计模式——装饰者模式

先说定义:动态地给一个对象添加一些额外的职责。就增加功能来说,装饰模式相比生成子类更为灵活。

这个模式属于结构型模式,比如我们给给自己的手机贴了膜,套上手机套,这就变成了一个不怕摔的手机,本质上还是手机,但是多了不怕摔的特性。所以,对于一个类,当要在不改变它的本质的基础上扩展一个类的时候,就需要装饰装饰了。

举一个在源码中的例子,就是大家很熟悉的Context:

Context是一个抽象类,也定义了很多抽象方法,ContextImpl是它的实现类,类ContextWrapper是它的装饰类。具体实现方式去这儿看

https://blog.csdn.net/jiujiaopanduola/article/details/105053059

我自己写的装饰模式例子:为列表装饰上拉加载的功能

(1)先写好主页面和加载更多,已加载全部的布局文件

(2)装饰者模式写适配器

首先写一个抽象类BaseAdapter,继承RecyclerView.Adapter,这个类只封装了与数据源相关的字段和方法:

public abstract class BaseAdapter<T> extends RecyclerView.Adapter {
    protected List<T> dataSet = new ArrayList<>();
    public void updateData(List dataSet) {//更新数据
        this.dataSet.clear();
        appendData(dataSet);
    }
    public void appendData(List dataSet) {//传数据
        if (dataSet != null && !dataSet.isEmpty()) {
            this.dataSet.addAll(dataSet);
            notifyDataSetChanged();
        }
    }
    public List<T> getDataSet() {
        return dataSet;
    }
    @Override
    public int getItemCount() {
        return dataSet.size();
    }
}

然后就是创建被装饰类,继承BaseAdapter,这个类就是很普通的adapter,展示数据

public class MyAdapter extends BaseAdapter<String> {
    private Context mContext;
    public MyAdapter(Context context) {
        mContext = context;
    }
    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(mContext).inflate(R.layout.list_item_mine, parent, false);
        return new MyViewHolder(v);
    }
    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        ((MyViewHolder) holder).bind(getDataSet().get(position));
    }
    static class MyViewHolder extends RecyclerView.ViewHolder {
        TextView mTextView;
        public MyViewHolder(View itemView) {
            super(itemView);
            mTextView = (TextView) itemView.findViewById(R.id.tv_content);
        }
        public void bind(CharSequence content) {
            mTextView.setText(content);
        }
    }
}

再然后开始写加载更多的adapter的装饰类,这个类只负责处理加载更多的逻辑,负责处理加载更多时的网络调用:

public class LoadMoreAdapterWrapper extends BaseAdapter<String> {
    private BaseAdapter mAdapter;
    private static final int mPageSize = 10;
    private int mPagePosition = 0;
    private boolean hasMoreData = true;
    private OnLoad mOnLoad;

    public LoadMoreAdapterWrapper(BaseAdapter adapter, OnLoad onLoad) {
        mAdapter = adapter;//传过来的adapter是需要被装饰的adapter
        mOnLoad = onLoad;//内部类,自定义的一个接口,可以回调处理加载更多的数据
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == R.layout.list_item_no_more) {//如果是已记载全部的布局就显示已加载完成
            View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
            return new NoMoreItemVH(view);
        } else if (viewType == R.layout.list_item_loading) {
            View view = LayoutInflater.from(parent.getContext()).inflate(viewType, parent, false);
            return new LoadingItemVH(view);
        } else {
            return mAdapter.onCreateViewHolder(parent, viewType);
        }
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
        if (holder instanceof LoadingItemVH) {//判断holder类型,如果是加载更多则请求数据
            requestData(mPagePosition, mPageSize);
        } else if (holder instanceof NoMoreItemVH) {

        } else {
            mAdapter.onBindViewHolder(holder, position);
        }
    }

    private void requestData(int pagePosition, int pageSize) {
        //网络请求,如果是异步请求,则在成功之后的回调中添加数据,并且调用notifyDataSetChanged方法,hasMoreData为true
        //如果没有数据了,则hasMoreData为false,然后通知变化,更新recylerview
        if (mOnLoad != null) {
            mOnLoad.load(pagePosition, pageSize, new ILoadCallback() {
                @Override
                public void onSuccess() {
                    notifyDataSetChanged();
                    mPagePosition = (mPagePosition + 1) * mPageSize;
                    hasMoreData = true;
                }

                @Override
                public void onFailure() {
                    hasMoreData = false;
                }
            });
        }
    }
    @Override
    public int getItemViewType(int position) {
        if (position == getItemCount() - 1) {//先判断position是不是最后一个,是的话就加载底部布局
            if (hasMoreData) {
                return R.layout.list_item_loading;
            } else {
                return R.layout.list_item_no_more;
            }
        } else {
            return mAdapter.getItemViewType(position);//不是就加在数据源数据
        }
    }
    @Override
    public int getItemCount() {
        return mAdapter.getItemCount() + 1;//因为有了底部view,所以数量总会比数据源数量多一个
    }
    static class LoadingItemVH extends RecyclerView.ViewHolder {
        public LoadingItemVH(View itemView) {
            super(itemView);
        }
    }
    static class NoMoreItemVH extends RecyclerView.ViewHolder {
        public NoMoreItemVH(View itemView) {
            super(itemView);
        }
    }

}
public interface OnLoad {
    void load(int pagePosition, int pageSize, ILoadCallback callback);
}
public interface ILoadCallback {
    void onSuccess();
    void onFailure();
}

 

最后一步:让那个很普通的adapter被装饰上可以加载更多的功能

public class MainActivity extends AppCompatActivity {
    RecyclerView mRecyclerView;
    BaseAdapter mAdapter;
    int loadCount;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = (RecyclerView) findViewById(R.id.recycler);
        //创建被装饰者类实例
        final MyAdapter adapter = new MyAdapter(this);
        //创建装饰者实例,并传入被装饰者和回调接口
        mAdapter = new LoadMoreAdapterWrapper(adapter, new OnLoad() {
            @Override
            public void load(int pagePosition, int pageSize, final ILoadCallback callback) {
                //此处模拟做网络操作,2s延迟,将拉取的数据更新到adpter中
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        List<String> dataSet = new ArrayList();
                        for (int i = 0; i < 10; i++) {
                            dataSet.add("我是一条数据");
                        }
                        //数据的处理最终还是交给被装饰的adapter来处理
                        adapter.appendData(dataSet);
                        callback.onSuccess();
                        //模拟加载到没有更多数据的情况,触发onFailure
                        if (loadCount++ == 3) {
                            callback.onFailure();
                        }
                    }
                }, 2000);
            }
        });
        mRecyclerView.setAdapter(mAdapter);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值