如何更好的优化 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() 方法来获取控件实例了。

完整代码如下

kotlin 复制代码
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,优化效果还是非常明显的。

相关推荐
8931519604 天前
Android开发教程随机数字验证码
android·android开发·android教程·android随机数字验证码
小曾同学.com24 天前
在 Android 应用程序中实现与WebSocket 服务器的实时通信
websocket·okhttp·android开发·handler·okhttpclient·websocket事件监听
螺蛳粉只吃炸蛋的走风2 个月前
面试题总结(四) -- STL与算法篇
开发语言·c++·算法·容器·stl·适配器
浩宇软件开发4 个月前
基于Android平台开发,天气预报APP
android·android studio·android开发
小曾同学.com4 个月前
ListView 的简单使用及 ArrayAdapter 中参数详解
android开发·listview·arrayadapter适配器·适配器adapter·arrayadapter 参数
Android每日一讲8 个月前
继深圳后,重庆与鸿蒙展开原生应用开发合作
华为·程序员·移动开发·harmonyos·openharmony·android开发·鸿蒙开发
代码与思维8 个月前
鸿蒙Harmony应用开发—ArkTS声明式开发(挂载卸载事件)
android·华为·harmonyos·鸿蒙·鸿蒙系统·android开发
itsover10 个月前
Android开发编程从入门到精通,安卓技术从初级到高级全套教学
android·android开发·android编程·安卓技术
爱桥代码的程序媛10 个月前
鸿蒙4.0实战教学—基础ArkTS(简易视频播放器)
华为·音视频·harmonyos·鸿蒙系统·android开发·程序员开发·鸿蒙开发