activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_height="match_parent"android:layout_width="match_parent"xmlns:tools="http://schemas.android.com/tools"><ListViewandroid:layout_width="match_parent"android:layout_height="wrap_content"android:id="@+id/lv"tools:listitem="@layout/myitem"/>
</LinearLayout>
myitem.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="horizontal"tools:ignore="UseCompoundDrawables"><ImageViewandroid:layout_width="100dp"android:layout_height="100dp"android:id="@+id/iv" /><TextViewandroid:layout_width="match_parent"android:layout_height="100dp"android:id="@+id/tv" />
</LinearLayout>
MainActivity.kt
class Item(val name:String, val imageId: Int){
}
class myAdapter(activity: Activity, val resourceId: Int, data: List<Item>) :ArrayAdapter<Item>(activity, resourceId, data) {inner class ViewHolder(val fruitImage: ImageView, val fruitName: TextView)// inner表示內部類override fun getView(position: Int, convertView: View?, parent: ViewGroup): View {val view: Viewval viewHolder: ViewHolder//通過緩存列表項的視圖對象來避免重復創建和填充視圖,從而提高列表的滑動性能//具體來說,ViewHolder 模式包含兩個部分://1.ViewHolder 類:用于保存列表項中的子視圖對象,例如 TextView、ImageView 等。// 通過保存子視圖對象,可以避免在每次滑動列表時都重新查找子視圖對象,提高列表的滑動性能。////2.getView() 方法:在 getView() 方法中,我們可以通過 convertView 參數來獲取之前創建的視圖對象,//并將其傳遞給 ViewHolder 對象。如果 convertView 不為空,則表示可以重用該視圖對象,// 否則需要創建新的視圖對象。通過重用視圖對象,可以避免重復創建和填充視圖,提高列表的滑動性能。val item = getItem(position)//根據當前位置來獲取適配器中對應位置的數據項,并將其顯示在視圖中。這時就可以使用 getItem() 方法來獲取數據項。if (convertView == null) {view = LayoutInflater.from(context).inflate(resourceId, parent, false)//from(context) 方法返回一個 LayoutInflater 對象// convertView是一個作為緩存的view,通過使用這個緩存可以替換掉用Inflater加載組件這一步val tv: TextView = view.findViewById(R.id.tv)val iv: ImageView = view.findViewById(R.id.iv)viewHolder = ViewHolder(iv, tv)// 創建對象view.tag = viewHolder// 將 ViewHolder 對象保存在當前列表項的視圖對象 view 的 tag 屬性中。// tag 屬性是一個 Object 類型的對象,可以用于保存任意類型的數據。// 在這里,我們將 ViewHolder 對象保存在 tag 屬性中,以便在下次滑動列表時能夠重用其中的子視圖對象。} else {view = convertViewviewHolder = view.tag as ViewHolder//從當前視圖對象 view 的 tag 屬性中獲取之前保存的 ViewHolder 對象,// 并將其賦值給當前的 viewHolder 變量。在之前創建視圖對象時,// 我們已經將 ViewHolder 對象保存在視圖對象的 tag 屬性中,因此在重用視圖對象時,// 可以通過 tag 屬性來獲取之前保存的 ViewHolder 對象,并重用其中的子視圖對象,}if (item != null) {viewHolder.fruitImage.setImageResource(item.imageId)viewHolder.fruitName.text = item.name// 這樣就避免了重復調用 findViewById() 函數,// 提高了列表的滑動性能。因此,可以從這里體現到了不用重復調用 findViewById() 函數。}return view}
}class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)enableEdgeToEdge()setContentView(R.layout.activity_main)val list = ArrayList<Item>()for(i in 1..10){list.add(Item("1",R.drawable.ic_launcher_background))list.add(Item("2",R.drawable.ic_launcher_foreground))}val adp = myAdapter(this,R.layout.myitem,list)val lv:ListView = findViewById(R.id.lv)lv.adapter = adplv.setOnItemClickListener{parent, view, position, id ->//parent、view、position 和 id,分別表示列表控件、當前點擊的列表項視圖、// 當前點擊的列表項位置和當前點擊的列表項 ID(如果有設置)。val item = list[position]Toast.makeText(this, item.name, Toast.LENGTH_SHORT).show()}}
}
用viewHolder可以緩存控件,可以減少findViewById函數的調用次數。
在?ListView
?或?RecyclerView
?等列表控件中,當滑動列表時,會重用之前創建的視圖對象,以避免重復創建和填充視圖,提高列表的滑動性能。因此,我們需要使用?ViewHolder
?對象來保存當前列表項中的子視圖對象,以便在下次滑動列表時能夠重用其中的子視圖對象。
ViewHolder
?對象的作用是在列表控件中重用子視圖對象,以提高列表的滑動性能。在?ViewHolder
?中,我們可以將子視圖對象作為成員變量保存起來,這樣在下次滑動列表時,就可以直接從?ViewHolder
?中獲取子視圖對象,而不需要再次調用?findViewById()
?函數來查找子視圖對象。
由于?findViewById()
?函數的調用是比較耗時的操作,因此使用?ViewHolder
?對象可以大大減少?findViewById()
?函數的調用次數,從而提高列表的滑動性能。此外,使用?ViewHolder
?對象還可以使代碼更加簡潔和易于維護。