Android Jetpack Compose remember 示範

直接使用兩個範例來方便了解 remember 的用途

範例一

這是一個產生隨機顏色的函式:
    
fun randomColor(): Color {
    return Color(
        red = (0..255).random(),
        green = (0..255).random(),
        blue = (0..255).random(),
        alpha = 255
    )
}
    

這是一個 Composable 函式,使用隨機顏色顯示傳入的文字:
    
@Composable
fun Message(text: String) {
    val color = randomColor()
    Text(
        text = text,
        color = color,
        modifier = Modifier.padding(16.dp)
    )
}
    

使用 TextField 建立輸入框,將輸入的內容同步顯示在上面建立的 Message 函式中:
嗯...怎麼和我想的不一樣?...

我想要的是每個 Message 會有不同的顏色,但是各個 Message 內容更新時一樣要維持同樣的顏色。但是當 Message 重繪時整個函式會重新執行一次,連 randomColor 的函式都重新讀取了,那不就要把顏色變為從外部傳入?確保顏色一樣

不過使用 remember 可以很容易的達成!上面的程式碼只要使用 remember 把 randomColor 包起來即可:
    
@Composable
fun Message(text: String) {
    val color = remember { randomColor() }
    Text(
        text = text,
        color = color,
        modifier = Modifier.padding(16.dp)
    )
}
    

第一次執行時就會自動記住 randomColor 的結果,就算因為傳入的內容不同而觸發 Message,顏色也會固定,並且多個獨立的 Message 也不會互相影響,會是不同的顏色:

範例二

AddQuote 會將輸入的數字前後加上雙引號,並產生 log,顯示資料已更新
    
fun AddQuote(input: Int): String {
    Log.i(TAG, "AddQuote: $input")
    return "\"$input\""
}
    

建立一個 Composable 函式,傳入兩個數字,將其顯示在畫面上:
    
@Composable
fun Message(number1: Int, number2: Int) {
    val str1: String = AddQuote(number1)
    val str2: String = AddQuote(number2)

    Text(
        text = "$str1 + $str2",
        modifier = Modifier.padding(16.dp, 0.dp, 16.dp, 16.dp)
    )
}
    

我們建立兩個 TextField 來輸入 number1 和 number2 ,在改變內容時無論是改變 number1 還是 number2 ,AddQuote 都會被觸發兩次,log 如下:
    
// 啟動時各執行一次
AddQuote: 1
AddQuote: 2
// 將 number1 變為 3
AddQuote: 3
AddQuote: 2
// 將 number2 變為 4
AddQuote: 3
AddQuote: 4
    

我們可以改用 remember 的另一種寫法,只有傳入的內容有改變時,才會執行 {} 內的程式碼
    
@Composable
fun Message(number1: Int, number2: Int) {
    val str1: String = remember(number1) { AddQuote(number1) }
    var str2: String = remember(number2) { AddQuote(number2) }

    Text(
        text = "$str1 + $str2",
        modifier = Modifier.padding(16.dp, 0.dp, 16.dp, 16.dp)
    )
}
    

執行時的 log :
    
// 啟動時各執行一次
AddQuote: 1
AddQuote: 2
// 將 number1 變為 3
AddQuote: 3
// 將 number2 變為 4
AddQuote: 4
    

可以發現只有數字改變的時候才會呼叫,當每次呼叫變得非常昂貴,需要處理很久時,remember 可以很好的充當「快取」,減少冗餘/重複的執行。

remember 是什麼

所以 remember 是什麼?remember 可以「記住」資訊,當 Composable 函式被觸發需要「更新」時,保護資料不被更新。並且也是很好的快取,除非指定的參數變更,才會「重新計算」取得新的內容。

參考資料:
Android Developers - State and Jetpack Compose
Youtube.Android Developers - Thinking in Compose

留言