iT邦幫忙

2021 iThome 鐵人賽

DAY 7
1
Mobile Development

認真學 Compose - 對 Jetpack Compose 的問題與探索系列 第 7

D07 / 怎麼顯示大量資料 - Lazy composables ( LazyColumn & StickyHeader )

  • 分享至 

  • xImage
  •  

今天大概會聊到的範圍

  • LazyColumn
  • StickyHeader

基本的畫面可以顯示了,但在 Android App 的開發中,我們很常需要顯示大量的資料:商品列表、景點列表、好友列表...。顯示列表可以說是 App UI 的基本功。

我們都知道可以使用 RecyclerView 來實現列表。在這個過程中,我們需要透過 Adapter 將資料 "adapt" 成畫面 ( 一個一個 view item )。並且,為了讓 View 可以重複使用、為了讓 findViewById 可以不要重複呼叫而造成浪費,我們需要 ViewHolder 來乘載 View 相關的元素,再透過 bind (onBindViewHolder) 將資料與 ViewHolder (view 本身)結合在一起。最後,為了讓列表中可以有多種個不同的項目,我們會用 viewType 來分辨,並用不同的 View 將這些 item 分開顯示。

在 Compose 中,顯示由上而下的元件自然會想到 Column。其實最簡單的列表顯示就是透過 Column,在 Column 中透過 for 迴圈其實就可以產生出一個列表

@Composable
fun ListView() {
    Column(...) {
        repeat(20) {
            ChildView()
        }
    }
}

但是這樣的列表並無法處理 Scolling 等行為,且會一次性的全部 render 出來。

在 Compose 中,有另一個工具更適合使用,那就是 Lazy composable。Lazy composable 最常見的有 LazyColumnLazyRow,可以想像成縱向和橫向的 RecyclerView。

LazyColumn 為例:

@Composable
fun ListView() {
    LazyColumn(...) {

        // 這個區塊是 LazyListScope
        
        item { Item() }
}

LazyColumn 的 trailing lambda 中是一個 LazyListScope。在 LazyListScope 中有三個常用的 function 來增加 item。

@Composable
fun ListView() {
    LazyColumn(...) {

        // 1. item { }
        item { Header() }
        
        // 2. items(count) { }
        items(20) { index ->
            Item()
        }
        
        // 3. items(data) { it -> }
        items(data) { Item(it)}
    }
}

第一種方法就是 item ,這個 function 可以增加單一個 Composable function 到 List 中。很適合用在 header 、footer 這種只出現一次,和別人都長得不一樣的項目上。這取代了以往需要將 header 、footer 硬轉成與列表同一個型別,並且塞進 RecyclerView Adapter 中,再用 viewType 將其分開的過程。或是可以省去使用較複雜的工具 (如 Epoxy )

第二種方式是 items(count),這個 function 可以單純的重複多次 item view。算是很單純產生大量資料的方式。在 items 的 lambda 中可以取得 index ,可以用來當作取得資料的依據。

第三個可能也是最常用的一種方式是 items(data),將已經處理成 List 的 data list 放進 items ,在 lambda 中取得單一一個 data 並且將其轉成 Composable 並顯示

Key

在使用 item / items 時,除了要顯示的內容之外,還可以提供一個 key

items(
    items = data,
    key = { item -> item.id }
) {
    Item(it)
}

這個 key 可以用來標明每個 item 的 id。若在 user 滑動之後有 data change,畫面上的第一個項目將會保持是同一個 key 的項目。

StickyHeader

另外分享一個有趣的功能,我們可以將任何一個 item 用 stickyHeader 取代。如此,當那個 item 滑動到最頂端時,就會停留在上方。

一個 LazyColumn 中也可以使用多個 stickyHeader,當每一個 stickyHeader 滑動到最上面時,都會取代前一個 stickyHeader

LazyColumn() {
    stickyHeader {
       // ...
    }
    item { ... }    
}

Reference:


上一篇
D06 / 為什麼 Modifier 的順序不能亂寫 - Modifier
下一篇
D08 / 怎麼做自己的 Modifier.padding? - Custom Layout Modifier
系列文
認真學 Compose - 對 Jetpack Compose 的問題與探索30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言