Android RecyclerView 滚动性能 [英] Android RecyclerView Scrolling Performance

查看:20
本文介绍了Android RecyclerView 滚动性能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我根据创建列表和卡片指南创建了 RecyclerView 示例.我的适配器有一个仅用于扩展布局的模式实现.

问题在于滚动性能不佳.这是在只有 8 个项目的 RecycleView 中.

在某些测试中,我验证了在 Android L 中不会出现此问题.但是在 KitKat 版本中,性能下降很明显.

解决方案

我最近遇到了同样的问题,所以这是我使用最新的 RecyclerView 支持库所做的:

  1. 用新优化的 ConstraintLayout 替换复杂的布局(嵌套视图,RelativeLayout).在 Android Studio 中激活它:转到 SDK Manager -> SDK Tools 选项卡 -> Support Repository -> 检查 ConstraintLayout for Android &ConstraintLayout 的求解器.添加到依赖项:

    compile 'com.android.support.constraint:constraint-layout:1.0.2'

  2. 如果可能,使 RecyclerView 的所有元素具有相同的高度.并添加:

    recyclerView.setHasFixedSize(true);

  3. 使用默认的 RecyclerView 绘图缓存 方法并根据您的情况调整它们.您不需要第三方库来执行此操作:

    recyclerView.setItemViewCacheSize(20);recyclerView.setDrawingCacheEnabled(true);recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);

  4. 如果您使用许多图像,请确保它们的大小和压缩是最佳的.缩放图像也可能影响性能.问题有两个方面 - 使用的源图像和解码的位图.以下示例为您提供了如何解码从网络下载的图像的提示:

    InputStream is = (InputStream) url.getContent();BitmapFactory.Options options = new BitmapFactory.Options();options.inPreferredConfig = Bitmap.Config.RGB_565;位图图像 = BitmapFactory.decodeStream(is, null, options);

最重要的部分是指定 inPreferredConfig - 它定义了图像的每个像素将使用多少字节.请记住,这是一个首选选项.如果源图像有更多颜色,它仍然会使用不同的配置进行解码.

  1. 确保 onBindViewHolder() 尽可能便宜.您可以在 onCreateViewHolder() 中设置一次 OnClickListener 并通过接口调用适配器外部的侦听器,传递单击的项目.这样您就不会一直创建额外的对象.在对此处的视图进行任何更改之前,还要检查标志和状态.

    viewHolder.itemView.setOnClickListener(new View.OnClickListener() {@覆盖公共无效onClick(查看视图){Item item = getItem(getAdapterPosition());externalClickListener.onItemClicked(item);}});

  2. 当数据发生变化时,尝试只更新受影响的项目.例如,在添加/加载更多项目时,不要使用 notifyDataSetChanged() 使整个数据集无效,只需使用:

    adapter.notifyItemRangeInserted(rangeStart, rangeEnd);适配器.notifyItemRemoved(位置);adapter.notifyItemChanged(position);适配器.notifyItemInserted(位置);

  3. 来自 Android 开发者网站 :

<块引用>

将 notifyDataSetChanged() 作为最后的手段.

但如果您需要使用它,请使用唯一 ID 维护您的项目:

 adapter.setHasStableIds(true);

<块引用>

RecyclerView 将尝试合成可见的结构变化报告它们具有稳定 ID 时的适配器的事件方法被使用.这有助于实现动画和视觉效果对象持久性,但仍需要单独的项目视图反弹并重新布局.

即使您做对了一切,RecyclerView 仍有可能没有像您希望的那样顺利运行.

I have created RecyclerView example basing on Creating Lists and Cards guide. My adapter have a pattern implementation only for inflate the layout.

The problem is the poor scrolling performance. This in a RecycleView with only 8 items.

In some tests I verified that in Android L this problem does not occurs. But in the KitKat version the decreasing of performance is evident.

解决方案

I've recently faced the same issue, so this is what I've done with the latest RecyclerView support library:

  1. Replace a complex layout (nested views, RelativeLayout) with the new optimized ConstraintLayout. Activate it in Android Studio: Go to SDK Manager -> SDK Tools tab -> Support Repository -> check ConstraintLayout for Android & Solver for ConstraintLayout. Add to the dependencies:

    compile 'com.android.support.constraint:constraint-layout:1.0.2'
    

  2. If possible, make all elements of the RecyclerView with the same height. And add:

    recyclerView.setHasFixedSize(true);
    

  3. Use the default RecyclerView drawing cache methods and tweak them according to your case. You don't need third party library to do so:

    recyclerView.setItemViewCacheSize(20);
    recyclerView.setDrawingCacheEnabled(true);
    recyclerView.setDrawingCacheQuality(View.DRAWING_CACHE_QUALITY_HIGH);
    

  4. If you use many images, make sure their size and compression are optimal. Scaling images may also affect the performance. There are two sides of the problem - the source image used and the decoded Bitmap. The following example gives you a hint how to decode аn image, downloaded from the web:

    InputStream is = (InputStream) url.getContent();
    BitmapFactory.Options options = new BitmapFactory.Options();
    options.inPreferredConfig = Bitmap.Config.RGB_565;
    Bitmap image = BitmapFactory.decodeStream(is, null, options);
    

The most important part is specifying inPreferredConfig - it defines how many bytes will be used for each pixel of the image. Keep in mind that this is a preferred option. If the source image has more colors, it will still be decoded with a different config.

  1. Make sure onBindViewHolder() is as cheap as possible. You can set OnClickListener once in onCreateViewHolder() and call through an interface a listener outside of the Adapter, passing the clicked item. This way you don't create extra objects all the time. Also check flags and states, before making any changes to the view here.

    viewHolder.itemView.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View view) {
              Item item = getItem(getAdapterPosition());
              outsideClickListener.onItemClicked(item);
          }
    });
    

  2. When data gets changed, try to update only the affected items. For example instead of invalidating the whole data set with notifyDataSetChanged(), when adding / loading more items, just use:

    adapter.notifyItemRangeInserted(rangeStart, rangeEnd);
    adapter.notifyItemRemoved(position);
    adapter.notifyItemChanged(position);
    adapter.notifyItemInserted(position);
    

  3. From Android Developer Web Site :

Rely on notifyDataSetChanged() as a last resort.

But if you need to use it, maintain your items with unique ids:

    adapter.setHasStableIds(true);

RecyclerView will attempt to synthesize visible structural change events for adapters that report that they have stable IDs when this method is used. This can help for the purposes of animation and visual object persistence but individual item views will still need to be rebound and relaid out.

Even if you do everything right, chances are that the RecyclerView is still not performing as smoothly as you would like.

这篇关于Android RecyclerView 滚动性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆