Kotlin玩Android第04篇 有效使用BaseAdapter 和 ViewHolder

本文章我們將去新建一個繼承BaseAdapter的Adapter類別,
讓我們可以創造更不一樣的Listview的item內容並且能了解到ArrayAdapter到底默默為我們實做了哪些內容。

建議搭配影片服用。


聲明:

此篇文章主要是我觀看Lets Build That App的影片來後實作驗證的心得,然後記錄其中的不足之處(Ex: Android官方API文件等等),文章最後有附上參考資料來源(有興趣可以當作延伸閱讀)。

BaseAdapter(用來定義專屬的Adapter)

這個類別是一個抽象類別,所以必須撰寫一個新類別去繼承它,
並且必須override 裡面的4個方法。

fun getView(postion: Int, convertView: View?, viewGroup: ViewGroup?): View
參數
position:指定回傳值view是回傳第幾行的view,例如0就代表是回傳的view是對應第0行的view。

converView: 曾經轉換過的view結果,需要判斷是否為空值。

viewGroup: view群組,可以間接取得呼叫getView的content,
例如: viewGroup!!.context
回傳
某一行的view(可以從參數position得知是哪一行)。

fun getItem(p0: Int): Any
參數
p0:取得第p0行的值
回傳
第p0的值,可能是字串或整數等等...依據你的資料來源而定。

fun getItemId(p0: Int): Long
回傳 第p0行的ID

fun getCount(): Int
回傳 資料來源有幾筆資料
這個回傳值的大小會影響到顯示item的筆數,
通常這樣用:return array.size

ViewHolder (ListView視圖的守護者)

參考官方說明:
Your code might call findViewById() frequently during the scrolling of ListView, which can slow down performance. Even when the Adapter returns an inflated view for recycling, you still need to look up the elements and update them. A way around repeated use of findViewById() is to use the "view holder" design pattern.
小古翻譯:
當你在捲動ListView時如果一直呼叫findViewById()將會導致效能低落。即使你的Adapter返回inflated view有回收(我想這裡指的recycling,指得是使用convertView的回收再利用),但你依舊需要在convertView中使用findViewById()去查找元素並更新他們。
有一種重複利用的方式是名為 view holder的設計模式。

說明:
簡單講就是view holder能幫助你的App在更新ListView(譬如說你滑動你的ListView畫面,這也是一種更新喔!)時,盡可能同個位置的view只呼叫一次findViewById(),之後就是都用之前呼叫findViewById產生的view物件來更新,但如果沒有配合RecyclerView依然會。
比喻:
如果把ListView比喻成高檔餐廳, 則每個view都是一個服務生,然後每個view所持有的值都是餐點,然後每次LIstView只能顯示5個View則代表餐廳一次只有五個餐桌,最多同時只有5個服務生服務。


沒用ViewHolder的話,就像是餐應每上一個新的餐點都要叫一個全新
的服務生,明明服務生叫五個了很夠用,但你身為錢多老闆就是每次上新餐點就是要用新的服務生,無節操的一直在招募新的員工,後台則塞滿了一堆舊服務生(來不及辭退XD),即使你能很快將他們辭退避免浪費?!(回收記憶體)但你依然要花費大量時間在聘請人才(浪費CPU時間)。



而如果使用ViewHolder的話,就像你身為一個台灣好老闆知道你們餐廳最多一次服務五個人,送完餐的服務生只要等待下次送餐就好,根本不用一直聘請和裁員只為了服務下位客人,你的餐廳至少穩定經營。








如何利用View Holder:
而建立一個ViewHolder可能就只要底下這樣一行
private class ViewHolder(val nameTextView: TextView, val postionTextView: TextView)



參考資料(文字):
BaseAdapter——convertView回收機制與動態控制項響
http://ohmerhe.com/2016/08/02/kotlin_one_method_no_viewholder/

參考資料(影片):




當使用listview,並且想要在runtime時期新增一個item。
有可能會出現這類錯誤。
Android, ListView IllegalStateException: “The content of the adapter has changed but ListView did not receive a notification”


https://stackoverflow.com/questions/3132021/android-listview-illegalstateexception-the-content-of-the-adapter-has-

留言

這個網誌中的熱門文章

Kotlin玩Android第03篇 Listview(01 ArrayAdapter)

使用Intent在Activity間傳遞資料(bundle)

golang本地測試如何繞過防火牆詢問允許