RecyclerView.Adapter优化了吗?
2017-07-16 16:02
148 查看
昨天写了一篇「还在用ListView?」讲的内容是RecyclerView的使用技巧以及一些经常使用的开源库。有朋友反馈“我已经在用recyclerview了”,那么怎样让它更好用呢?此时我想到了优化RecyclerView.Adapter,由于在RecyclerView还没出来之前我就写过一篇「ListView之Adapter优化」,通过这篇文章的优化思路能够在原来的代码上改动部分代码用在优化RecyclerView.Adapter上,一如既往的好用。
本次主要讲两个方面的优化
精简代码
扩展功能
精简代码
正常没优化的写法:public class DefAdpater extends RecyclerView.Adapter<DefAdpater.ViewHolder> { private final List<Status> sampleData = DataServer.getSampleData(); private Context mContext; public DefAdpater(Context context) { mContext = context; } @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View item = LayoutInflater.from(parent.getContext()).inflate(R.layout.tweet, parent, false); return new ViewHolder(item); } @Override public void onBindViewHolder(ViewHolder holder, int position) { Status status = sampleData.get(position); holder.name.setText(status.getUserName()); holder.text.setText(status.getText()); holder.date.setText(status.getCreatedAt()); Picasso.with(mContext).load(status.getUserAvatar()).into(holder.avatar); holder.rt.setVisibility(status.isRetweet() ? View.VISIBLE : View.GONE); } @Override public int getItemCount() { return sampleData.size(); } public static class ViewHolder extends RecyclerView.ViewHolder { private ImageView avatar; private ImageView rt; private TextView name; private TextView date; private TextView text; public ViewHolder(View itemView) { super(itemView); text = (TextView) itemView.findViewById(R.id.tweetText); name = (TextView) itemView.findViewById(R.id.tweetName); date = (TextView) itemView.findViewById(R.id.tweetDate); avatar = (ImageView) itemView.findViewById(R.id.tweetAvatar); rt = (ImageView) itemView.findViewById(R.id.tweetRT); } } }
优化后,是这种:
public class QuickAdapter extends BaseQuickAdapter<Status> { public QuickAdapter(Context context) { super(context, R.layout.tweet, DataServer.getSampleData()); } @Override protected void convert(BaseAdapterHelper helper, Status item) { helper.setText(R.id.tweetName, item.getUserName()) .setText(R.id.tweetText, item.getText()) .setText(R.id.tweetDate, item.getCreatedAt()) .setImageUrl(R.id.tweetAvatar, item.getUserAvatar()) .setVisible(R.id.tweetRT, item.isRetweet()) .linkify(R.id.tweetText); } }
优化前和优化后的代码量是3:1的比例!
我的天啦!
太不可思议了!
如今来分析,怎样优化的?(带着问题学习)
思路:
找到反复部分代码,抽取到基类,非反复部分用抽象方法取代,详细让子类实现。
说了思路在看看详细代码BaseQuickAdapter里面怎么写的:
@Override public int getItemCount() { return data.size(); } @Override public BaseAdapterHelper onCreateViewHolder(ViewGroup parent, int viewType) { View item = LayoutInflater.from(parent.getContext()).inflate(layoutResId, parent, false); return new BaseViewHolder(context, item); } @Override public void onBindViewHolder(BaseViewHolder holder, final int position) { convert(holder, data.get(position)); } protected abstract void convert(BaseViewHolder helper, T item);
接下来再看看BaseViewHolder怎么写的:
public class BaseViewHolder extends RecyclerView.ViewHolder { private final SparseArray<View> views; private final Context context; private View convertView; protected BaseViewHolder(Context context, View view) { super(view); this.context = context; this.views = new SparseArray<View>(); convertView = view; } protected <T extends View> T retrieveView(int viewId) { View view = views.get(viewId); if (view == null) { view = convertView.findViewById(viewId); views.put(viewId, view); } return (T) view; } public BaseViewHolder setText(int viewId, CharSequence value) { TextView view = retrieveView(viewId); view.setText(value); return this; } public BaseViewHolder setImageUrl(int viewId, String imageUrl) { ImageView view = retrieveView(viewId); Picasso.with(context).load(imageUrl).into(view); return this; } public BaseViewHolder setVisible(int viewId, boolean visible) { View view = retrieveView(viewId); view.setVisibility(visible ? View.VISIBLE : View.GONE); return this; } public BaseViewHolder linkify(int viewId) { TextView view = retrieveView(viewId); Linkify.addLinks(view, Linkify.ALL); return this; } //此处省略若干经常使用赋值经常用法 }
利用SparseArray来做缓存,把经常用法所有写好,从而避免冗余代码。
扩展功能
大家都知道RecyclerView没有ItemClick方法,能够在上面提过的BaseQuickAdapter里面加入ItemClick,能够这样:网上有非常多写法都是在
onBindViewHolder里面写,功能是能够实现可是会导致频繁创建,应该在
onCreateViewHolder()中每次为新建的 View 设置一次即可了。
private OnRecyclerViewItemClickListener onRecyclerViewItemClickListener; public void setOnRecyclerViewItemClickListener(OnRecyclerViewItemClickListener onRecyclerViewItemClickListener) { this.onRecyclerViewItemClickListener = onRecyclerViewItemClickListener; } public interface OnRecyclerViewItemClickListener { public void onItemClick(View view, int position); } @Override public void onCreateViewHolder(ViewGroup parent, int viewType) { // init ViewHolder ... if (onRecyclerViewItemClickListener != null) { holder.getView().setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { onRecyclerViewItemClickListener.onItemClick(v, holder.getLayoutPosition()); } }); } }
还能够加入一些经常使用的方法如:
public void remove(int position) { data.remove(position); notifyItemRemoved(position); } public void add(int position, T item) { data.add(position, item); notifyItemInserted(position); }
代码我已经上传到GitHub上了,有兴趣的同学Star或者一起共同将它完毕的更完好。送大家一句我非常喜欢的话:不分享谁与你共享呢?
源代码地址:传送门
相关文章推荐
- RecyclerView的ViewHolder和Adapter的封装优化
- RecyclerView.Adapter的优化与封装
- RecyclerView.Adapter优化了吗?
- RecyclerView的基本使用(优化图片加载、设置条目间距、设置Adapter、设置点击事件等)
- 优化recyclerview的adapter代码
- Recyclerview adapter.notify几个方法内存占用分析
- BaseRecyclerViewAdapterHelper开源项目之BaseQuickAdapter源码学习BaseViewHolder扩展功能的实现代码学习(四)
- Android中利用ViewHolder优化自定义Adapter的典型写法
- RecyclerView的Adapter万能适配包
- 突发奇想,把RecyclerView的Adapter封装了一下,留着自己用
- RecyclerView Adapter简单封装
- 福利:打造一个万能的RecyclerViewAdapter
- ListView(优化),自定义Layout和adapter,entity,ViewHolder,ConvertView用法案例(phone)
- Android RecyclerView Adapter Item not match_partent
- RecyclerView.Adapter调用顺序
- BaseRecyclerViewAdapterHelper开源项目之BaseSectionQuickAdapter 实现分组效果的源码学习
- Android代码实现AdapterViews和RecyclerView无限滚动
- BaseRecyclerViewAdapterHelper开源项目之点击事件源码学习
- SectionedRecyclerViewAdapter
- BaseRecyclerViewAdapterHelper 上拉加载过程产生的问题