昨天写了一篇「还在用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.Adapter优化了吗?的更多相关文章

  1. 极简的Android RecyclerView Adapter(使用DataBinding)

    阅读本篇文章需要读者对Android Databinding和RecyclerView有一定的了解. 简介 我们知道,DataBinding的核心理念是数据驱动.数据驱动驱动的目标就是View,使用D ...

  2. Android 利用RecyclerView.Adapter刷新列表中的单个view问题

    首先使用RecyclerView的adapter继承:RecyclerView.Adapter public class OrderListAdapter extends RecyclerView.A ...

  3. Android RecyclerView.Adapter notifyDataSetChanged 不起作用

    我在自己动手写RecyclerView的上拉加载更多,最后就差一步,这个时候数据已经加载完了,UI上面没有显示,我而且也调用了notifyDataSetChanged刷新item的数据,但是一直没效果 ...

  4. Android RecyclerView Adapter 新式用法之SortedListAdapterCallback

    引言 前几天在同事的提醒下发现V7中有了一个新的工具类SortedListAdapterCallback,配合RecyclerView Adapter和SortedList一起使用更加方便的管理我们在 ...

  5. RecyclerView.Adapter封装,最简单实用的BaseRecyclerViewAdapter;只需重写一个方法,设置数据链式调用;

    之前对ListView的BaseAdapter进行过封装,只需重写一个getView方法: 现在慢慢的RecyclerView成为主流,下面是RecyclerView.Adapter的封装: Base ...

  6. Android开发教程 - 使用Data Binding(六)RecyclerView Adapter中的使用

    本系列目录 使用Data Binding(一)介绍 使用Data Binding(二)集成与配置 使用Data Binding(三)在Activity中的使用 使用Data Binding(四)在Fr ...

  7. Adapter优化方案的探索

    概要:使用Adapter的注意事项与优化方案本文的例子都可以在结尾处的示例代码连接中看到并下载,如果喜欢请star,如果觉得有纰漏请提交issue,如果你有更好的点子可以提交pull request. ...

  8. [原]Android开发优化-Adapter优化

    ListView作为Android开发中使用频率最高的一个控件,保证ListView的流畅运行,对用户体验的提高至关重要.Adapter是ListView和数据源之间的中间人,当每条数据进入可见区时, ...

  9. RecyclerView.Adapter

    RecyclerView无需多说,是用于替代ListView的新控件.它的适配器在于灵活. 现在有一个需求:需要RecyclerView的item支持点击事件,并且下拉到最后时,显示ProgressB ...

随机推荐

  1. 双色球js

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. elastic-search单机部署以及中文分词IKAnalyzer安装

    前提条件 elasticsearch使用版本5.6.3,需要jdk版本1.8,低于该版本不能使用 下载 https://artifacts.elastic.co/downloads/elasticse ...

  3. C# Ioc容器Unity,简单实用

    开头先吐槽一下博客园超级不好用,添加图片后就写不动字了,难道是bug 好进入正题,先来说下依赖注入,简单来说就是定义好接口,上层代码调用接口,具体实现通过配置文件方式去指定具体实现类. 首先我们需要通 ...

  4. 6. ZooKeeper访问控制列表

    ZooKeeper的数据模型提供了ACL机制来控制访问znode. 在创建znode时,ACL将确定你可以在znode上执行的各种操作的权限. ZooKeeper ACL模型与Unix / Linux ...

  5. Centos下配置tomcat7的https证书

    近期搞定了HTTPS配置,特此记录. 1.把下载的文件拷贝到cert文件夹,然后放在tomcat根目录下(与conf同一级目录).2.配置conf下的server.xml,修改下面3个节点,如下: & ...

  6. 激光相机数据融合(5)--Gazebo仿真数据融合

    这一节将用ROS+Gazebo 环境获取激光获取点云,并用PCL和OPENCV处理,源代码在:https://github.com/ZouCheng321/5_laser_camera_sim 由于激 ...

  7. EditText 限制输入整数和小数 的位数

    如题,本文主要说的就是  如何限制 EditText 中 可输入整数和小数 的位数 . 近期,由于公司业务需求中有价格输入功能,给出的要求说是,必须整数能输入几位,小数能输入几位...好嘛,产品一句话 ...

  8. CentOS 7 yum 安装ownCloud 搭建云盘服务器

    基于CentOS7.0 64位系统+ownCloud 10.0 稳定版本构建 ownCloud 是一个开源免费专业的私有云存储项目,它能帮你快速在个人电脑或服务器上架设一套专属的私有云文件同步网盘,可 ...

  9. OPENGLES 绘制纹理带黑圈pre-multiplying

    1. 问题 在进行 OpenGL 纹理混合的过程中,遇到一个诡异的现象,两个纹理混合的效果出人所料: 将一个ALPHA渐变的[胡须]加在另一张图片上,这个 [胡须]是由外向里逐渐增加透明度的,也就是最 ...

  10. windows配置caffe + python和matlab接口

    参考: http://blog.csdn.net/baidu_26408419/article/details/53711640 http://www.cnblogs.com/love6tao/p/5 ...