😄作者简介: 小曾同学.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,优化效果还是非常明显的。