如何更好的优化 ListView 控件的性能

😄作者简介: 小曾同学.com,一个致力于测试开发的博主⛽️,主要职责:测试开发、CI/CD,日常还会涉及Android开发工作。
如果文章知识点有错误的地方,还请大家指正,让我们一起学习,一起进步。
😊 座右铭:不想当开发的测试,不是一个好测试✌️。
热衷分享,喜欢原创,如果觉得博主的文章还不错的话,还请点赞、收藏哦!👍

前言 🌟

之前给大家分享过 定制化 ListView 控件,我们以这个 demo 为参照对象,来对比优化前后的性能。

优化点🪐

  • 布局优化
    convertView 参数用于将之前加载好的布局进行缓存。
  • 控件获取优化——ViewHolder

ListView 控件说是最难用的控件,有一个缺点就是性能较差,有很多细节需要优化,比如,每次展示 ListView 子项时就会调用一次 getView() 方法

在这里插入图片描述
我们会发现在 getView() 方法的参数中,有一个 convertView 参数我们还没有使用,打印下 convertView 的值为 nul,这个参数主要是用于将之前加载好的布局进行缓存。

在这里插入图片描述
将第一次加载好的布局进行缓存,后续进行复用,是不是就可以提高性能。还有一个问题,我们将 converView 的数量打印出来,数量是13,而我们这个真机界面上展示的子视图是11,为什么还多2个呢?一般情况下为了能够正常显示足够数量的子项,ListView 会根据屏幕的高度以及每个子项的高度来计算出屏幕可见区域能够容纳的子项数量,这个数量被称为可见子项数(Visible Item Count)。

Visible Item Count = 屏幕高度 / 单个子项高度

防止每次都调用 findViewbyId() 方法,可以将控件的实例进行缓存,就需要 ViewHolder ViewHolder 的作用是持有列表项的视图组件的引用,并在适配器中进行缓存。通过在首次创建列表项时,通过 findViewById() 方法找到视图组件,并将其存储在 ViewHolder 对象中。然后,在后续调用中可以直接访问 ViewHolder 中的视图组件,而无需再次查找。

新增内部类 ViewHolder ,创建一个 ViewHolder 对象,并将控件的实例存放在 ViewHolder 里,然后调用 View 的 setTag() 方法,将 ViewHolder 对象存储在 View 中。当convertView 不为 null 的时候,则调用 View 的 getTag() 方法,把 ViewHolder 重新取出。这样所有控件的实例都缓存在了 ViewHolder 里,
就没有必要每次都通过 findViewById() 方法来获取控件实例了。

完整代码如下

class FruitAdapter (activity: Activity,val resourceId: Int,data:List<Fruit>):ArrayAdapter<Fruit>(activity,resourceId,data) {
    inner class ViewHolder(val fruitImage:ImageView,val fruitName:TextView)
    //private var i = 0
    override fun getView(position: Int,convertView: View?,parent:ViewGroup):View{
        //Log.i("getView被调用","次数 ${i++}")
        //Log.i("converView"," $convertView")
        val view:View
        val viewHolder:ViewHolder
        if (convertView == null) {
            view = LayoutInflater.from(context).inflate(resourceId, parent, false)
            //Log.i("第一次加载布局"," $view")
            val fruitImage:ImageView = view.findViewById(R.id.fruitImage)
            val fruitName:TextView = view.findViewById(R.id.fruitName)
            viewHolder = ViewHolder(fruitImage,fruitName)
            view.tag = viewHolder
        }else{
            view = convertView
            //Log.i("后续加载布局"," $view")
            viewHolder = view.tag as ViewHolder
        }
        val fruit = getItem(position) //获取当前项的Fruit实例
        if(fruit != null){
            viewHolder.fruitImage.setImageResource(fruit.imageId)
            viewHolder.fruitName.text = fruit.name
        }
        return  view
    }
}

我们来对比优化前后的内存占用情况
优化前:
在这里插入图片描述优化后:
在这里插入图片描述
优化前后内存相差14MB,优化效果还是非常明显的。

在这里插入图片描述

  • 10
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
ListView 和 RecyclerView 都是 Android 开发中用于展示列表数据的视图组件,它们在功能上相似但有一些关键的区别: 1. **性能优化**: - ListView 在早期版本的 Android 中被广泛使用,但它在处理大量数据或滚动时性能较差,因为它是基于 AbsListView 实现的,内存管理相对较低效。 - RecyclerView 是 Android Lollipop(API 21)之后引入的,采用的是更先进的数据集适配器和视图缓存机制,能更好地处理大规模数据并实现流畅的滚动。 2. **布局管理器**: - ListView 使用的是 ListView.LayoutParams,而 RecyclerView 利用了其内置的 LayoutManager API,如 LinearLayoutManager、GridLayoutManager 等,提供了更灵活的布局方式。 3. **分页和加载更多**: - ListView 不支持直接的分页和滚动到顶部/底部加载更多功能。若要实现,开发者需要自定义滚动监听等。 - RecyclerView 内置了 CoordinatorLayout 的能力,可以轻松地配合 CoordinatorLayout 实现常见的加载更多效果,以及与 AppBarLayout 的协同。 4. **适应性**: - ListView 对于高度固定的布局(如 ListAdapter)表现较好,但不太适合自定义布局或瀑布流样式的数据展示。 - RecyclerView 支持多种视图类型(itemAnimator、ViewHolder等),可以提供更丰富的视觉效果和交互体验。 5. **扩展性和可维护性**: - RecyclerView 提供了更多的扩展点,使得定制化更加方便,且社区资源丰富,易于找到解决方案。 - ListView 的扩展性相对较弱,如果要进行深度定制可能需要更多的代码量。 相关问题: 1. ListView 和 RecyclerView 的哪个更适合处理大数据量? 2. 如何在 RecyclerView 中实现滚动到顶部的加载更多功能? 3. 如何利用 RecyclerView 的 LayoutManager 来创建瀑布流布局?

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小曾同学.com

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值