RecyclerView性能优化分析

RecyclerView有着极高的灵活性,能实现ListView、GridView的所有功能。在日常开发中,使用非常广泛,如果使用不当将会影响到应用的整体性能,所以有必要了解一下如何更高效的使用。

数据处理与视图绑定分离

RecyclerView的 

 

class Task {    Date dateDue;    String title;    String description;
    // getters and setters here}
class MyRecyclerView.Adapter extends RecyclerView.Adapter {
    static final TODAYS_DATE = new Date();    static final DATE_FORMAT = new SimpleDateFormat("MM dd, yyyy");
    public onBindViewHolder(Task.ViewHolder tvh, int position) {        Task task = getItem(position);
        if (TODAYS_DATE.compareTo(task.dateDue) > 0) {            tvh.backgroundView.setColor(Color.GREEN);        } else {            tvh.backgroundView.setColor(Color.RED);        }
        String dueDateFormatted = DATE_FORMAT.format(task.getDateDue());        tvh.dateTextView.setDate(dueDateFormatted);    }}

 

上面的 onBindViewHolder方法中进行了日期的比较和日期的格式化,这个是很耗时的,在 onBindViewHolder方法中,应该只是将数据 set到视图中,而不应进行业务的处理。

优化后:

public class TaskViewModel {    int overdueColor;    String dateDue;}
public onBindViewHolder(Task.ViewHolder tvh, int position) {    TaskViewModel taskViewModel = getItem(position);    tvh.backgroundView.setColor(taskViewModel.getOverdueColor());    tvh.dateTextView.setDate(taskViewModel.getDateDue());}

数据优化

  1. 分页加载远端数据,对拉取的远端数据进行缓存,提高二次加载速度;

  2. 对于新增或删除数据通过 DiffUtil,来进行局部数据刷新,而不是一味的全局刷新数据。

DiffUtil是support包下新增的一个工具类,用来判断新数据和旧数据的差别,从而进行局部刷新。

DiffUtil的使用,在原来调用 mAdapter.notifyDataSetChanged()的地方:

 

// mAdapter.notifyDataSetChanged()DiffUtil.DiffResult diffResult = DiffUtil.calculateDiff(new DiffCallBack(oldDatas, newDatas), true);diffResult.dispatchUpdatesTo(mAdapter);

DiffUtil最终是调用Adapter的下面几个方法来进行局部刷新:

mAdapter.notifyItemRangeInserted(position, count);mAdapter.notifyItemRangeRemoved(position, count);mAdapter.notifyItemMoved(fromPosition, toPosition);mAdapter.notifyItemRangeChanged(position, count, payload);。

布局优化

减少过度绘制

减少布局层级,可以考虑使用自定义View来减少层级,或者更合理的设置布局来减少层级。

Note: 目前不推荐在RecyclerView中使用 ConstraintLayout,在ConstraintLayout1.1.2版中,性能还是表现不佳,后续的版本可能这个问题就解决了,需要持续关注。

减少xml文件inflate时间

xml文件包括:layout、drawable的xml,xml文件inflate出ItemView是通过耗时的IO操作。可以使用代码去生成布局,即 newView()的方式。这种方式是比较麻烦,但是在布局太过复杂,或对性能要求比较高的时候可以使用。

减少View对象的创建

一个稍微复杂的 Item 会包含大量的 View,而大量的 View 的创建也会消耗大量时间,所以要尽可能简化 ItemView;设计 ItemType 时,对多 ViewType 能够共用的部分尽量设计成自定义 View,减少 View 的构造和嵌套。

设置高度固定

如果item高度是固定的话,可以使用 RecyclerView.setHasFixedSize(true);来避免requestLayout浪费资源。

共用RecycledViewPool

在嵌套RecyclerView中,如果子RecyclerView具有相同的adapter,那么可以设置 RecyclerView.setRecycledViewPool(pool)来共用一个RecycledViewPool。

Note: 如果LayoutManager是LinearLayoutManager或其子类,需要手动开启这个特性: layout.setRecycleChildrenOnDetach(true)

class OuterAdapter extends RecyclerView.Adapter<OuterAdapter.ViewHolder> {    RecyclerView.RecycledViewPool mSharedPool = new RecyclerView.RecycledViewPool();
...
    @Override    public OuterAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        RecyclerView innerLLM = new RecyclerView(inflater.getContext());
        LinearLayoutManager innerLLM = new LinearLayoutManager(parent.getContext(), LinearLayoutManager.HORIZONTAL);        innerLLM.setRecycleChildrenOnDetach(true);        innerRv.setLayoutManager(innerLLM);        innerRv.setRecycledViewPool(mSharedPool);        return new OuterAdapter.ViewHolder(innerRv);    }

RecyclerView数据预取

RecyclerView25.1.0及以上版本增加了 Prefetch功能。用于嵌套RecyclerView获取最佳性能。

Note: 只适合横向嵌套

// 在嵌套内部的LayoutManager中调用LinearLayoutManger的设置方法// num的取值:如果列表刚刚展示4个半item,则设置为5innerLLM.setInitialItemsPrefetchCount(num);

 

加大RecyclerView的缓存

用空间换时间,来提高滚动的流畅性。

原创文章,作者:速盾高防cdn,如若转载,请注明出处:https://www.sudun.com/ask/79125.html

(0)
速盾高防cdn's avatar速盾高防cdn
上一篇 2024年5月30日 下午5:51
下一篇 2024年5月30日 下午5:54

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注