RecyclerView.Adapter优化了吗?
昨天写了一篇「还在用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优化了吗?的更多相关文章
- 极简的Android RecyclerView Adapter(使用DataBinding)
阅读本篇文章需要读者对Android Databinding和RecyclerView有一定的了解. 简介 我们知道,DataBinding的核心理念是数据驱动.数据驱动驱动的目标就是View,使用D ...
- Android 利用RecyclerView.Adapter刷新列表中的单个view问题
首先使用RecyclerView的adapter继承:RecyclerView.Adapter public class OrderListAdapter extends RecyclerView.A ...
- Android RecyclerView.Adapter notifyDataSetChanged 不起作用
我在自己动手写RecyclerView的上拉加载更多,最后就差一步,这个时候数据已经加载完了,UI上面没有显示,我而且也调用了notifyDataSetChanged刷新item的数据,但是一直没效果 ...
- Android RecyclerView Adapter 新式用法之SortedListAdapterCallback
引言 前几天在同事的提醒下发现V7中有了一个新的工具类SortedListAdapterCallback,配合RecyclerView Adapter和SortedList一起使用更加方便的管理我们在 ...
- RecyclerView.Adapter封装,最简单实用的BaseRecyclerViewAdapter;只需重写一个方法,设置数据链式调用;
之前对ListView的BaseAdapter进行过封装,只需重写一个getView方法: 现在慢慢的RecyclerView成为主流,下面是RecyclerView.Adapter的封装: Base ...
- Android开发教程 - 使用Data Binding(六)RecyclerView Adapter中的使用
本系列目录 使用Data Binding(一)介绍 使用Data Binding(二)集成与配置 使用Data Binding(三)在Activity中的使用 使用Data Binding(四)在Fr ...
- Adapter优化方案的探索
概要:使用Adapter的注意事项与优化方案本文的例子都可以在结尾处的示例代码连接中看到并下载,如果喜欢请star,如果觉得有纰漏请提交issue,如果你有更好的点子可以提交pull request. ...
- [原]Android开发优化-Adapter优化
ListView作为Android开发中使用频率最高的一个控件,保证ListView的流畅运行,对用户体验的提高至关重要.Adapter是ListView和数据源之间的中间人,当每条数据进入可见区时, ...
- RecyclerView.Adapter
RecyclerView无需多说,是用于替代ListView的新控件.它的适配器在于灵活. 现在有一个需求:需要RecyclerView的item支持点击事件,并且下拉到最后时,显示ProgressB ...
随机推荐
- [译]ASP.NET Core 2.0 区域
问题 如何将一个规模庞大的ASP.NET Core 2.0应用程序进行逻辑分组? 答案 新建一个ASP.NET Core 2.0空项目,修改Startup类,增加Mvc服务和中间件: public v ...
- SQL Server 2008对日期时间类型的改进
微软在备受多年的争议后,终于对日期时间数据类型开刀了,在新版的SQL Server 2008中一口气增加了4种新的日期时间数据类型,包括: Date:一个纯的日期数据类型. Time:一个纯的时间数据 ...
- mysql查询锁表及解锁
SHOW PROCESSLIST; KILL ; 锁表网上解释: 这牵涉到mysql的事务,简单通俗的话,就这样给你解释有一个任务序列控制sql语句的执行,第一次有select的语句查询表a,mysq ...
- 【ThinkPHP框架学习 】(2) --- 后台管理系统如何用iframe点击左边右边局部刷新
如题: 在写后台管理系统时,需要实现后台界面的局部动态刷新. 左边的导航栏使用a标签进行设置,通过href和target属性的配合,就可以将iframe中的子页实现动态 ...
- JS-类型转换
类型转换 值 转字符串 数字 布尔值 对象 undefined 'undefined' 0 false throws TypeError null 'null' 0 false throws Type ...
- Kotlin(二) 函数定义
1.不带参数,不返回值的函数 fun sum(){} 2.带参数,不带返回值的函数 fun sum(a:Int){} 3.带参数,带返回值的函数 fun sum(a:Int,b:Int) : Int{ ...
- [转载] Java线程池框架源码分析
转载自http://www.linuxidc.com/Linux/2014-11/108791.htm 相关类Executor,Executors,AbstractExecutorService,Ex ...
- Ajax-javascript
一.Web 2.0的特点 提到Ajax不得不提到WEB2.0 1.用户贡献内容 2.内容聚合RSS 3.更丰富的"用户体验" 二.Ajax的作用 无刷新:不刷新整个页面,只刷新局部 ...
- 1)C语言简介(C自考学习)
C语言历史由来 世界上第一个高级语言是"ALFOL",而C的前身是ALGOL语言.1970年美国贝尔实验室的肯·汤普逊对BCPL(基本复合程序设计语言)进行了进一步的简化,突出了硬 ...
- 登山(Climb)
题目: Rocky山脉有n个山峰,一字排开,从西向东依次编号为1, 2, 3, --, n.每个山峰的高度都是不一样的.编号为i的山峰高度为hi. 小修从西往东登山.每到一座山峰,她就回头观望自己走 ...