昨天写了一篇「还在用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. .NET项目从CI到CD-Jenkins_Pipeline的应用

    一.罗里吧嗦 最近迁移了服务器,顺道完善下服役了一两年的Jenkins服务,主要是把Slave搭建起来,还有等等.本文只是我对Jenkins Pipeline的一些自己的理解与应用,欢迎指出错误,欢迎 ...

  2. [J2EE] 有关 PreparedStatement

    今天同事遇到一个问题,简言之,就是PreparedStatement的预编译究竟是怎么发挥作用的... 嘿嘿,说来惭愧,我以前就只知道PreparedStatement比Statement要好,要防S ...

  3. HTML5对音视频的处理

      前  言 现在网上有许多的框架和插件,能够满足程序猿的各种需求,慢慢的,就有些忽视最基础的东西. 比如,大多数视频是通过插件(比如 Flash)来显示的.然而,并非所有浏览器都拥有同样的插件. H ...

  4. C#里调用 MysqlDB

    最近在做项目,发现在使用Mysql提供给C#操作的类不是和好用,就想办法写了一个操作方便的Mysql数据层类. 比如以前在执 行一个查询 代码                              ...

  5. [转载] Java线程池框架源码分析

    转载自http://www.linuxidc.com/Linux/2014-11/108791.htm 相关类Executor,Executors,AbstractExecutorService,Ex ...

  6. pt-query-digest

    pt-query-digest默认查询时间分布 # Query_time distribution # 1us # 10us ##################################### ...

  7. Shiro SpringMVC 非maven HelloWorld

    项目用到Shiro就从网上找一些案例看看吧,结果看了很多都是maven的,没有办法就自己弄了一个.废话不多说,原理自己找开始上菜. 配置web.xml <?xml version="1 ...

  8. JMS学习之路(一):整合activeMQ到SpringMVC 转载:http://www.cnblogs.com/xiaochangwei/p/5426639.html

    JMS的全称是Java Message Service,即Java消息服务.它主要用于在生产者和消费者之间进行消息传递,生产者负责产生消息,而消费者负责接收消息.把它应用到实际的业务需求中的话我们可以 ...

  9. UWP更改标题栏颜色

    你是否因为UWP标题栏太丑而想过改变?那么这篇文章或许可以帮助你美化UWP界面,让你的UWP的标题栏也变好看 这里的代码,都要在MainPage的构造函数中.如果你在App类中更改了首页,则在该首页的 ...

  10. Python 集合整理