RecyclerView.Adapter优化了吗?
来源:互联网 发布:购买淘宝小号在哪里买 编辑:程序博客网 时间:2024/05/20 07:14
昨天写了一篇「还在用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里面怎么写的:
@Overridepublic int getItemCount() { return data.size();}@Overridepublic BaseAdapterHelper onCreateViewHolder(ViewGroup parent, int viewType) { View item = LayoutInflater.from(parent.getContext()).inflate(layoutResId, parent, false); return new BaseViewHolder(context, item);}@Overridepublic 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);}@Overridepublic 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.Adapter优化了吗?
- 优化recyclerview的adapter代码
- RecyclerView.Adapter的优化与封装
- 不用再写RecyclerView的Adapter了,一个Adapter搞定
- 不用再写RecyclerView的Adapter了,一个Adapter搞定
- RecyclerView.Adapter
- Recyclerview adapter
- RecyclerView的ViewHolder和Adapter的封装优化
- RecyclerView+RecyclerView.Adapter+RecyclerView.ViewHolder的使用
- 能用RecyclerView.Adapter
- 封装RecyclerView.Adapter
- RecyclerView.Adapter中的viewType
- RecyclerView Adapter 封装
- RecyclerView.Adapter notifyDataSetChanged 不起作用
- RecyclerView万能的Adapter
- RecyclerView,Adapter和ViewHolder
- simple封装RecyclerView.Adapter
- RecyclerView 设置adapter
- 区间调度问题
- 4. PDO 事务处理
- window对象
- 华为OJ题目(二十一):输入n个整数,输出其中最小的k个
- malloc和calloc函数的深入理解
- RecyclerView.Adapter优化了吗?
- char类型和Unicode编码
- servlet/filter/listener/interceptor区别与联系
- email正则表达式 验证邮箱格式
- 1005. 继续(3n+1)猜想 (25)
- Git入门
- 剑指offer系列之5:用两个栈来实现队列
- *windows.event对象在ie与ff中的区别**
- 冒泡排序、选择和插入排序、二分法查找