Android View Holder
ID |
kotlin.android_view_holder |
Severity |
low |
Remediation Complexity |
trivial |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Efficiency |
Language |
Kotlin |
Tags |
android, best-practice, efficiency |
Description
Reports unconditional calls to inflate(…) inside a getView(int, View, ViewGroup)
override of an adapter subclass (BaseAdapter, ArrayAdapter, CursorAdapter).
Rationale
class BadAdapter : BaseAdapter() {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
val v = inflater.inflate(R.layout.row, parent, false) // FLAW
return v
}
}
class GoodAdapter : BaseAdapter() {
override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {
if (convertView == null) {
return inflater.inflate(R.layout.row, parent, false)
}
return convertView // OK — reuse
}
}
The ViewHolder pattern requires reusing the convertView parameter when it is non-null and
inflating a new layout only when it is null. Unconditional inflation defeats view recycling
and produces poor scrolling performance in list views.
Remediation
-
Guard the
inflate(…)call withif (convertView == null)and return the existing view otherwise. -
Use the elvis operator:
val v = convertView ?: inflater.inflate(…). -
Where possible, migrate to
RecyclerViewand the built-inViewHolderlifecycle.