State และ Jetpack Compose

สถานะในแอปคือค่าใดก็ตามที่เปลี่ยนแปลงได้เมื่อเวลาผ่านไป ซึ่งเป็นคำจำกัดความที่กว้างมาก และครอบคลุมทุกอย่างตั้งแต่ฐานข้อมูล Room ไปจนถึงตัวแปรใน คลาส

แอป Android ทั้งหมดจะแสดงสถานะต่อผู้ใช้ ตัวอย่างสถานะในแอป Android

  • แถบข้อความที่แสดงเมื่อสร้างการเชื่อมต่อเครือข่ายไม่ได้
  • บล็อกโพสต์และความคิดเห็นที่เกี่ยวข้อง
  • ภาพเคลื่อนไหวแบบระลอกบนปุ่มซึ่งจะเล่นเมื่อผู้ใช้คลิก
  • สติกเกอร์ที่ผู้ใช้สามารถวาดทับรูปภาพได้

Jetpack Compose ช่วยให้คุณระบุได้อย่างชัดเจนว่าจะจัดเก็บและใช้สถานะในแอป Android ที่ใดและอย่างไร คู่มือนี้มุ่งเน้นที่ความเชื่อมโยงระหว่างสถานะกับ Composable รวมถึง API ที่ Jetpack Compose มีให้เพื่อทำงานกับสถานะได้ง่ายขึ้น

สถานะและองค์ประกอบ

Compose เป็นแบบประกาศ ดังนั้นวิธีเดียวที่จะอัปเดตได้คือการเรียกใช้ Composable เดียวกันด้วยอาร์กิวเมนต์ใหม่ อาร์กิวเมนต์เหล่านี้เป็นการแสดงสถานะ UI ทุกครั้งที่มีการอัปเดตสถานะ จะเกิดการประกอบใหม่ ด้วยเหตุนี้ TextField จึงไม่อัปเดตโดยอัตโนมัติเหมือนกับใน มุมมองที่อิงตาม XML แบบคำสั่ง Composable ต้องได้รับแจ้งสถานะใหม่โดยชัดแจ้ง จึงจะอัปเดตตามนั้นได้

@Composable
private fun HelloContent() {
    Column(modifier = Modifier.padding(16.dp)) {
        Text(
            text = "Hello!",
            modifier = Modifier.padding(bottom = 8.dp),
            style = MaterialTheme.typography.bodyMedium
        )
        OutlinedTextField(
            value = "",
            onValueChange = { },
            label = { Text("Name") }
        )
    }
}

หากคุณเรียกใช้คำสั่งนี้และพยายามป้อนข้อความ คุณจะเห็นว่าไม่มีอะไรเกิดขึ้น เนื่องจาก TextField จะไม่อัปเดตตัวเอง แต่จะอัปเดตเมื่อพารามิเตอร์ value มีการเปลี่ยนแปลง ซึ่งเป็นผลมาจากวิธีการทำงานของการคอมโพสและการคอมโพสใหม่ใน Compose

ดูข้อมูลเพิ่มเติมเกี่ยวกับการเรียบเรียงครั้งแรกและการเรียบเรียงใหม่ได้ที่ การคิดใน Compose

สถานะใน Composable

ฟังก์ชันที่ประกอบได้จะใช้ API ของ remember เพื่อจัดเก็บออบเจ็กต์ไว้ในหน่วยความจำได้ ค่าที่คำนวณโดย remember จะ จัดเก็บไว้ในองค์ประกอบระหว่าง การจัดองค์ประกอบครั้งแรก และค่าที่จัดเก็บไว้จะแสดงผลระหว่างการจัดองค์ประกอบใหม่ remember ใช้จัดเก็บทั้งออบเจ็กต์ที่เปลี่ยนแปลงได้และเปลี่ยนแปลงไม่ได้

mutableStateOf สร้าง Observable MutableState<T> ซึ่งเป็นประเภท Observable ที่ผสานรวมกับรันไทม์ของ Compose

interface MutableState<T> : State<T> {
    override var value: T
}

การเปลี่ยนแปลงใดๆ ในตารางเวลา value จะทำให้ฟังก์ชันที่ประกอบได้ซึ่งอ่าน value ต้องประกอบใหม่

มี 3 วิธีในการประกาศออบเจ็กต์ MutableState ใน Composable ดังนี้

  • val mutableState = remember { mutableStateOf(default) }
  • var value by remember { mutableStateOf(default) }
  • val (value, setValue) = remember { mutableStateOf(default) }

การประกาศเหล่านี้เทียบเท่ากันและมีไว้เพื่อเป็นไวยากรณ์ที่กระชับสำหรับการใช้งานสถานะที่แตกต่างกัน คุณควรเลือกตัวเลือกที่สร้างโค้ดที่อ่านง่ายที่สุดใน Composable ที่คุณเขียน

ไวยากรณ์ของตัวแทน by ต้องมีการนำเข้าต่อไปนี้

import androidx.compose.runtime.getValue
import androidx.compose.runtime.setValue

คุณสามารถใช้ค่าที่จดจำไว้เป็นพารามิเตอร์สำหรับ Composable อื่นๆ หรือแม้แต่เป็น ตรรกะในคำสั่งเพื่อเปลี่ยน Composable ที่แสดง ตัวอย่างเช่น หากคุณไม่ต้องการแสดงคำทักทายหากชื่อว่าง ให้ใช้สถานะในคำสั่ง if ดังนี้

@Composable
fun HelloContent() {
    Column(modifier = Modifier.padding(16.dp)) {
        var name by remember { mutableStateOf("") }
        if (name.isNotEmpty()) {
            Text(
                text = "Hello, $name!",
                modifier = Modifier.padding(bottom = 8.dp),
                style = MaterialTheme.typography.bodyMedium
            )
        }
        OutlinedTextField(
            value = name,
            onValueChange = { name = it },
            label = { Text("Name") }
        )
    }
}

แม้ว่า remember จะช่วยให้คุณคงสถานะไว้ได้เมื่อมีการเขียนคอมโพสซ้ำ แต่สถานะจะไม่คงอยู่เมื่อมีการเปลี่ยนแปลงการกำหนดค่า โดยคุณต้องใช้ rememberSaveable rememberSaveable จะบันทึกค่าที่บันทึกได้ใน Bundle โดยอัตโนมัติ สำหรับค่าอื่นๆ คุณสามารถส่งออบเจ็กต์โปรแกรมประหยัดที่กำหนดเองได้

แทนการใช้ออบเจ็กต์ที่เปลี่ยนแปลงได้ซึ่งสังเกตไม่ได้

ประเภทสถานะอื่นๆ ที่รองรับ

Compose ไม่ได้กำหนดให้คุณใช้ MutableState<T> เพื่อเก็บสถานะ แต่รองรับประเภทที่สังเกตได้อื่นๆ ก่อนที่จะอ่านประเภทที่สังเกตได้อีกประเภทใน Compose คุณต้องแปลงเป็น State<T> เพื่อให้ Composable สามารถ ทำการ Recompose โดยอัตโนมัติเมื่อสถานะเปลี่ยนแปลง

Compose มาพร้อมกับฟังก์ชันสำหรับสร้าง State<T> จากประเภท Observable ทั่วไปที่ใช้ในแอป Android ก่อนใช้การผสานรวมเหล่านี้ ให้เพิ่มอาร์ติแฟกต์ที่เหมาะสมตามที่ระบุไว้ด้านล่าง

  • Flow: collectAsStateWithLifecycle()

    collectAsStateWithLifecycle() จะรวบรวมค่าจาก a Flow ในลักษณะที่รับรู้ถึงวงจรของแอป ซึ่งช่วยให้แอปของคุณ ประหยัดทรัพยากรของแอปได้ ซึ่งแสดงถึงค่าล่าสุดที่ปล่อยออกมาจาก Compose State ใช้ API นี้เป็นวิธีที่แนะนําในการรวบรวมโฟลว์ในแอป Android

    ต้องมี Dependency ต่อไปนี้ในไฟล์ build.gradle (ควรเป็นเวอร์ชัน 2.6.0-beta01 ขึ้นไป)

Kotlin

dependencies {
      ...
      implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.7")
}

Groovy

dependencies {
      ...
      implementation "androidx.lifecycle:lifecycle-runtime-compose:2.8.7"
}
  • Flow: collectAsState()

    collectAsState คล้ายกับ collectAsStateWithLifecycle เนื่องจากยัง รวบรวมค่าจาก Flow และแปลงเป็น Compose State ด้วย

    ใช้ collectAsState สำหรับโค้ดที่ไม่ขึ้นอยู่กับแพลตฟอร์มแทน collectAsStateWithLifecycle ซึ่งใช้ได้เฉพาะใน Android

    collectAsState ไม่ต้องมีทรัพยากรเพิ่มเติมเนื่องจากมีอยู่ใน compose-runtime

  • LiveData: observeAsState()

    observeAsState() เริ่มสังเกต LiveData นี้และแสดงค่าผ่าน State

    ต้องมีการขึ้นต่อกันต่อไปนี้ในไฟล์ build.gradle

Kotlin

dependencies {
      ...
      implementation("androidx.compose.runtime:runtime-livedata:1.8.1")
}

Groovy

dependencies {
      ...
      implementation "androidx.compose.runtime:runtime-livedata:1.8.1"
}

Kotlin

dependencies {
      ...
      implementation("androidx.compose.runtime:runtime-rxjava2:1.8.1")
}

Groovy

dependencies {
      ...
      implementation "androidx.compose.runtime:runtime-rxjava2:1.8.1"
}

Kotlin

dependencies {
      ...
      implementation("androidx.compose.runtime:runtime-rxjava3:1.8.1")
}

Groovy

dependencies {
      ...
      implementation "androidx.compose.runtime:runtime-rxjava3:1.8.1"
}

เก็บสถานะเทียบกับไม่เก็บสถานะ

Composable ที่ใช้ remember เพื่อจัดเก็บออบเจ็กต์จะสร้างสถานะภายใน ทำให้ Composable เป็น stateful HelloContent เป็นตัวอย่างของ Composable ที่มีสถานะ เนื่องจากเก็บและแก้ไขสถานะ name ภายใน ซึ่งอาจมีประโยชน์ในกรณีที่ผู้โทรไม่จำเป็นต้องควบคุมสถานะและใช้ได้โดยไม่ต้องจัดการสถานะด้วยตนเอง อย่างไรก็ตาม Composable ที่มี สถานะภายในมักจะนำกลับมาใช้ซ้ำได้น้อยกว่าและทดสอบได้ยากกว่า

Composable แบบไม่มีสถานะคือ Composable ที่ไม่มีสถานะ วิธีง่ายๆ ในการทำให้เป็นแบบไม่เก็บสถานะคือการใช้การยกสถานะ

เมื่อพัฒนา Composable ที่นำกลับมาใช้ใหม่ได้ คุณมักจะต้องการแสดงทั้งเวอร์ชันที่มีสถานะ และเวอร์ชันที่ไม่มีสถานะของ Composable เดียวกัน เวอร์ชันที่มีสถานะจะสะดวกสำหรับผู้โทรที่ไม่สนใจสถานะ และเวอร์ชันที่ไม่มีสถานะจำเป็นสำหรับผู้โทรที่ต้องการควบคุมหรือยกสถานะ

การย้ายสถานะ

การยกระดับสถานะใน Compose เป็นรูปแบบการย้ายสถานะไปยังผู้เรียกของ Composable เพื่อให้ Composable เป็นแบบไม่มีสถานะ รูปแบบทั่วไปสำหรับการยกระดับสถานะใน Jetpack Compose คือการแทนที่ตัวแปรสถานะด้วยพารามิเตอร์ 2 รายการ ดังนี้

  • value: T: ค่าปัจจุบันที่จะแสดง
  • onValueChange: (T) -> Unit: เหตุการณ์ที่ขอให้เปลี่ยนค่า โดย T คือค่าใหม่ที่เสนอ

แต่คุณไม่ได้จำกัดอยู่แค่ onValueChange หากมีเหตุการณ์ที่เฉพาะเจาะจงมากขึ้น ซึ่งเหมาะกับ Composable คุณควรกำหนดเหตุการณ์เหล่านั้นโดยใช้ Lambda

State ที่ยกขึ้นด้วยวิธีนี้มีพร็อพเพอร์ตี้ที่สำคัญบางอย่าง ดังนี้

  • แหล่งข้อมูลที่เชื่อถือได้เพียงแหล่งเดียว: การย้ายสถานะแทนการทำซ้ำจะช่วยให้มั่นใจได้ว่ามีแหล่งข้อมูลที่เชื่อถือได้เพียงแหล่งเดียว ซึ่งจะช่วยหลีกเลี่ยงข้อบกพร่อง
  • แคปซูล: มีเพียง Composable แบบมีสถานะเท่านั้นที่แก้ไขสถานะของตนเองได้ ซึ่งเป็น ข้อมูลภายในทั้งหมด
  • แชร์ได้: สถานะที่ยกขึ้นสามารถแชร์กับ Composable หลายรายการได้ หากคุณต้องการอ่าน name ใน Composable อื่น การยกจะช่วยให้คุณทำเช่นนั้นได้
  • สกัดกั้นได้: ผู้โทรไปยัง Composable แบบไม่มีสถานะสามารถเลือกที่จะ ไม่สนใจหรือแก้ไขเหตุการณ์ก่อนที่จะเปลี่ยนสถานะ
  • แยกส่วน: สถานะของ Composable แบบไม่มีสถานะอาจจัดเก็บได้ทุกที่ เช่น ตอนนี้คุณสามารถย้าย name ไปยัง ViewModel ได้แล้ว

ในกรณีตัวอย่าง คุณจะแยก name และ onValueChange ออกจาก HelloContent แล้วย้ายขึ้นไปในโครงสร้างไปยัง Composable HelloScreen ที่เรียก HelloContent

@Composable
fun HelloScreen() {
    var name by rememberSaveable { mutableStateOf("") }

    HelloContent(name = name, onNameChange = { name = it })
}

@Composable
fun HelloContent(name: String, onNameChange: (String) -> Unit) {
    Column(modifier = Modifier.padding(16.dp)) {
        Text(
            text = "Hello, $name",
            modifier = Modifier.padding(bottom = 8.dp),
            style = MaterialTheme.typography.bodyMedium
        )
        OutlinedTextField(value = name, onValueChange = onNameChange, label = { Text("Name") })
    }
}

การย้ายสถานะออกจาก HelloContent ทำให้การให้เหตุผลเกี่ยวกับ คอมโพสابل การนำกลับมาใช้ใหม่ในสถานการณ์ต่างๆ และการทดสอบทำได้ง่ายขึ้น HelloContent ไม่ได้ เชื่อมโยงกับวิธีจัดเก็บสถานะ การแยกส่วนหมายความว่าหากคุณแก้ไขหรือ แทนที่ HelloScreen คุณก็ไม่จำเป็นต้องเปลี่ยนวิธี การติดตั้งใช้งาน HelloContent

รูปแบบที่สถานะลดลงและเหตุการณ์เพิ่มขึ้นเรียกว่าการไหลของข้อมูลแบบทิศทางเดียว ในกรณีนี้ สถานะจะลดลงจาก HelloScreen เป็น HelloContent และเหตุการณ์จะเพิ่มขึ้นจาก HelloContent เป็น HelloScreen การทำตามโฟลว์ข้อมูลแบบทิศทางเดียวจะช่วยให้คุณแยก Composable ที่แสดงสถานะใน UI ออกจากส่วนต่างๆ ของแอปที่จัดเก็บและเปลี่ยนสถานะได้

ดูข้อมูลเพิ่มเติมได้ที่หน้าตำแหน่งที่จะยกระดับสถานะ

การคืนค่าสถานะใน Compose

rememberSaveable API ทำงานคล้ายกับ remember เนื่องจาก รักษาสถานะไว้ในการจัดองค์ประกอบใหม่ และยังรักษาสถานะไว้ในกิจกรรมหรือกระบวนการ ที่สร้างขึ้นใหม่โดยใช้กลไกสถานะอินสแตนซ์ที่บันทึกไว้ เช่น เมื่อหมุนหน้าจอ

วิธีจัดเก็บสถานะ

ระบบจะบันทึกประเภทข้อมูลทั้งหมดที่เพิ่มลงใน Bundle โดยอัตโนมัติ หากต้องการบันทึกสิ่งที่เพิ่มลงในBundleไม่ได้ คุณมีตัวเลือกหลายอย่างดังนี้

แบ่งพัสดุ

โซลูชันที่ง่ายที่สุดคือการเพิ่มคำอธิบายประกอบ @Parcelize ลงในออบเจ็กต์ ออบเจ็กต์จะกลายเป็น Parcelable และสามารถจัดกลุ่มได้ ตัวอย่างเช่น โค้ดนี้จะสร้างCityประเภทข้อมูลที่ส่งผ่านได้และบันทึกลงใน สถานะ

@Parcelize
data class City(val name: String, val country: String) : Parcelable

@Composable
fun CityScreen() {
    var selectedCity = rememberSaveable {
        mutableStateOf(City("Madrid", "Spain"))
    }
}

MapSaver

หาก@Parcelizeไม่เหมาะสมด้วยเหตุผลบางประการ คุณสามารถใช้ mapSaver เพื่อ กำหนดกฎของคุณเองในการแปลงออบเจ็กต์เป็นชุดค่าที่ระบบ บันทึกลงใน Bundle ได้

data class City(val name: String, val country: String)

val CitySaver = run {
    val nameKey = "Name"
    val countryKey = "Country"
    mapSaver(
        save = { mapOf(nameKey to it.name, countryKey to it.country) },
        restore = { City(it[nameKey] as String, it[countryKey] as String) }
    )
}

@Composable
fun CityScreen() {
    var selectedCity = rememberSaveable(stateSaver = CitySaver) {
        mutableStateOf(City("Madrid", "Spain"))
    }
}

ListSaver

หากไม่ต้องการกำหนดคีย์สำหรับแผนที่ คุณสามารถใช้ listSaver และใช้อินเด็กซ์เป็นคีย์ได้ด้วย

data class City(val name: String, val country: String)

val CitySaver = listSaver<City, Any>(
    save = { listOf(it.name, it.country) },
    restore = { City(it[0] as String, it[1] as String) }
)

@Composable
fun CityScreen() {
    var selectedCity = rememberSaveable(stateSaver = CitySaver) {
        mutableStateOf(City("Madrid", "Spain"))
    }
}

ตัวเก็บสถานะใน Compose

การเลื่อนสถานะอย่างง่ายจะจัดการได้ในฟังก์ชันที่ใช้ Compose เอง อย่างไรก็ตาม หากปริมาณสถานะที่ต้องติดตามเพิ่มขึ้น หรือมีตรรกะที่ต้อง ดำเนินการในฟังก์ชันที่ใช้ร่วมกันได้ แนวทางปฏิบัติแนะนำคือการมอบหมายความรับผิดชอบด้านตรรกะและสถานะให้กับคลาสอื่นๆ ซึ่งก็คือที่เก็บสถานะ

ดูข้อมูลเพิ่มเติมได้ในเอกสารประกอบเกี่ยวกับการยกระดับสถานะใน Compose หรือหน้าที่เก็บสถานะและสถานะ UI ในคำแนะนำด้านสถาปัตยกรรม

ทริกเกอร์การคำนวณการจดจำอีกครั้งเมื่อคีย์มีการเปลี่ยนแปลง

โดยทั่วไปจะใช้ remember API ร่วมกับ MutableState ดังนี้

var name by remember { mutableStateOf("") }

ในที่นี้ การใช้ฟังก์ชัน remember จะทำให้ค่า MutableState ยังคงอยู่ หลังจากการเขียนใหม่

โดยทั่วไป remember จะใช้พารามิเตอร์แลมบ์ดา calculation เมื่อเรียกใช้ remember เป็นครั้งแรก ฟังก์ชันจะเรียกใช้ Lambda calculation และจัดเก็บผลลัพธ์ ในระหว่างการ ประกอบใหม่ remember จะแสดงค่าที่จัดเก็บไว้ล่าสุด

นอกจากการแคชสถานะแล้ว คุณยังใช้ remember เพื่อจัดเก็บออบเจ็กต์หรือผลลัพธ์ของการดำเนินการใดๆ ใน Composition ที่มีค่าใช้จ่ายสูงในการเริ่มต้นหรือคำนวณได้ด้วย คุณอาจไม่ต้องการคำนวณซ้ำในการจัดองค์ประกอบใหม่ทุกครั้ง ตัวอย่างเช่น การสร้างออบเจ็กต์ ShaderBrush นี้ซึ่งเป็นการดำเนินการที่มีค่าใช้จ่ายสูง

val brush = remember {
    ShaderBrush(
        BitmapShader(
            ImageBitmap.imageResource(res, avatarRes).asAndroidBitmap(),
            Shader.TileMode.REPEAT,
            Shader.TileMode.REPEAT
        )
    )
}

remember จะจัดเก็บค่าไว้จนกว่าจะออกจาก Composition อย่างไรก็ตาม มี วิธีทำให้ค่าที่แคชใช้ไม่ได้ remember API ยังใช้พารามิเตอร์ key หรือ keys ด้วย หากคีย์เหล่านี้มีการเปลี่ยนแปลง เมื่อฟังก์ชันrememberสร้างใหม่ในครั้งถัดไป ระบบจะล้างแคชและเรียกใช้บล็อก Lambda ของการคำนวณอีกครั้ง กลไกนี้ช่วยให้คุณควบคุมอายุของออบเจ็กต์ในคอมโพสิตได้ การคำนวณจะยังคงใช้ได้จนกว่าอินพุตจะ เปลี่ยนแปลง แทนที่จะใช้ได้จนกว่าค่าที่จดจำไว้จะออกจาก Composition

ตัวอย่างต่อไปนี้แสดงวิธีการทำงานของกลไกนี้

ในข้อมูลโค้ดนี้ ShaderBrush จะได้รับการสร้างขึ้นและใช้เป็นสีพื้นหลัง ของ Box ที่ใช้ร่วมกันได้ remember จะจัดเก็บอินสแตนซ์ ShaderBrush เนื่องจากค่าใช้จ่ายในการสร้างใหม่นั้นสูง ดังที่ได้อธิบายไว้ก่อนหน้านี้ remember ใช้ avatarRes เป็นพารามิเตอร์ key1 ซึ่งเป็นภาพพื้นหลังที่เลือก หากavatarResมีการเปลี่ยนแปลง พู่กันจะจัดองค์ประกอบใหม่ด้วยรูปภาพใหม่และนำไปใช้กับBoxอีกครั้ง ปัญหานี้อาจเกิดขึ้นเมื่อผู้ใช้เลือกรูปภาพอื่นเป็น พื้นหลังจากเครื่องมือเลือก

@Composable
private fun BackgroundBanner(
    @DrawableRes avatarRes: Int,
    modifier: Modifier = Modifier,
    res: Resources = LocalContext.current.resources
) {
    val brush = remember(key1 = avatarRes) {
        ShaderBrush(
            BitmapShader(
                ImageBitmap.imageResource(res, avatarRes).asAndroidBitmap(),
                Shader.TileMode.REPEAT,
                Shader.TileMode.REPEAT
            )
        )
    }

    Box(
        modifier = modifier.background(brush)
    ) {
        /* ... */
    }
}

ในข้อมูลโค้ดถัดไป สถานะจะได้รับการยกขึ้นไปยังคลาสที่เก็บสถานะธรรมดา MyAppState ซึ่งจะแสดงrememberMyAppStateฟังก์ชันเพื่อเริ่มต้นอินสแตนซ์ของคลาสโดยใช้ remember การเปิดเผยฟังก์ชันดังกล่าวเพื่อสร้าง อินสแตนซ์ที่ยังคงอยู่หลังจากการจัดองค์ประกอบใหม่เป็นรูปแบบที่พบบ่อยใน Compose ฟังก์ชัน rememberMyAppState จะรับ windowSizeClass ซึ่งทำหน้าที่เป็น พารามิเตอร์ key สำหรับ remember หากพารามิเตอร์นี้มีการเปลี่ยนแปลง แอปจะต้อง สร้างคลาสที่เก็บสถานะธรรมดาขึ้นใหม่ด้วยค่าล่าสุด ซึ่งอาจเกิดขึ้นได้หากผู้ใช้หมุนอุปกรณ์ เป็นต้น

@Composable
private fun rememberMyAppState(
    windowSizeClass: WindowSizeClass
): MyAppState {
    return remember(windowSizeClass) {
        MyAppState(windowSizeClass)
    }
}

@Stable
class MyAppState(
    private val windowSizeClass: WindowSizeClass
) { /* ... */ }

Compose ใช้การติดตั้งใช้งาน equals ของคลาสเพื่อพิจารณาว่าคีย์มีการเปลี่ยนแปลงหรือไม่ และทำให้ค่าที่จัดเก็บใช้ไม่ได้

จัดเก็บสถานะด้วยคีย์นอกเหนือจากการจัดองค์ประกอบใหม่

rememberSaveable API เป็น Wrapper รอบ remember ที่จัดเก็บ ข้อมูลใน Bundle ได้ API นี้ช่วยให้สถานะยังคงอยู่ได้ไม่เพียงแค่ การประกอบใหม่ แต่ยังรวมถึงการสร้างกิจกรรมใหม่และการสิ้นสุดกระบวนการที่ระบบเริ่มต้นด้วย rememberSaveable ได้รับพารามิเตอร์ input เพื่อวัตถุประสงค์เดียวกันกับที่ remember ได้รับ keys แคชจะใช้ไม่ได้เมื่ออินพุตใดก็ตามมีการเปลี่ยนแปลง ในครั้งถัดไปที่ฟังก์ชันนี้สร้างขึ้นใหม่ rememberSaveable จะเรียกใช้ บล็อก Lambda ของการคำนวณอีกครั้ง

ในตัวอย่างต่อไปนี้ rememberSaveable จะจัดเก็บ userTypedQuery จนกว่าtypedQuery จะมีการเปลี่ยนแปลง

var userTypedQuery by rememberSaveable(typedQuery, stateSaver = TextFieldValue.Saver) {
    mutableStateOf(
        TextFieldValue(text = typedQuery, selection = TextRange(typedQuery.length))
    )
}

ดูข้อมูลเพิ่มเติม

ดูข้อมูลเพิ่มเติมเกี่ยวกับสถานะและ Jetpack Compose ได้จาก แหล่งข้อมูลเพิ่มเติมต่อไปนี้

ตัวอย่าง

Codelabs

วิดีโอ

บล็อก