เขียนและไลบรารีอื่นๆ

คุณสามารถใช้ไลบรารีที่ชอบใน Compose ได้ ส่วนนี้อธิบายวิธีการ รวบรวมไลบรารีที่มีประโยชน์มากที่สุด 2-3 แบบ

กิจกรรม

หากต้องการใช้ฟีเจอร์ "เขียน" ในกิจกรรม คุณต้องใช้ ComponentActivity คลาสย่อยของ Activity ที่ให้ LifecycleOwner และ ในการเขียน นอกจากนี้ยังมี API เพิ่มเติมที่ถอดรหัสโค้ดของคุณ ไม่ให้ลบล้างเมธอดในคลาสกิจกรรมของคุณ การเขียนกิจกรรม แสดง API เหล่านี้กับ Composable ซึ่งลบล้างเมธอดที่อยู่นอกเหนือแท็ก ไม่จำเป็นต้องใช้ Composables หรือการเรียกข้อมูลอินสแตนซ์ Activity ที่ชัดเจนอีกต่อไป นอกจากนี้ API เหล่านี้ยังช่วยดูแลให้ API เหล่านี้เริ่มทำงานเพียงครั้งเดียวเท่านั้น การจัดองค์ประกอบใหม่ และล้างข้อมูลอย่างเหมาะสมหาก Composable ถูกนำออกจาก องค์ประกอบ

ผลลัพธ์ของกิจกรรม

rememberLauncherForActivityResult() API ช่วยให้คุณทำสิ่งต่อไปนี้ รับผลลัพธ์จากกิจกรรม ใน Composable:

@Composable
fun GetContentExample() {
    var imageUri by remember { mutableStateOf<Uri?>(null) }
    val launcher = rememberLauncherForActivityResult(ActivityResultContracts.GetContent()) { uri: Uri? ->
        imageUri = uri
    }
    Column {
        Button(onClick = { launcher.launch("image/*") }) {
            Text(text = "Load Image")
        }
        Image(
            painter = rememberAsyncImagePainter(imageUri),
            contentDescription = "My Image"
        )
    }
}

ตัวอย่างนี้แสดง GetContent() สัญญา การแตะปุ่มจะเป็นการเปิดคำขอ แลมบ์ดาตามด้วย rememberLauncherForActivityResult() จะมีการเรียกเมื่อผู้ใช้เลือกรูปภาพและกลับไปยังกิจกรรมการเปิด การดําเนินการนี้จะโหลดรูปภาพที่เลือกโดยใช้ rememberImagePainter() ของ Coil

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

การขอสิทธิ์รันไทม์

API ของผลลัพธ์กิจกรรมเดียวกันและ rememberLauncherForActivityResult() ที่อธิบายไว้ข้างต้นสามารถใช้เพื่อ ขอสิทธิ์รันไทม์ โดยใช้ RequestPermission สำหรับการอนุญาตรายการเดียวหรือ RequestMultiplePermissions สำหรับการให้สิทธิ์หลายรายการ

คลังสิทธิ์ Accompanist นอกจากนี้ยังสามารถใช้เลเยอร์เหนือ API เหล่านั้นเพื่อจับคู่สถานะการให้สิทธิ์ปัจจุบันสำหรับ ลงในสถานะที่ UI ของ Compose สามารถใช้ได้

การจัดการปุ่มย้อนกลับของระบบ

วิธีระบุการนำทางกลับที่กำหนดเอง และแทนที่การทำงานเริ่มต้นของปุ่มย้อนกลับของระบบจากภายใน Composable แล้ว Composable สามารถใช้แอตทริบิวต์ BackHandler ที่จะสกัดกั้นเหตุการณ์นั้นได้ดังนี้

var backHandlingEnabled by remember { mutableStateOf(true) }
BackHandler(backHandlingEnabled) {
    // Handle back press
}

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

ViewModel

ถ้าคุณใช้คอมโพเนนต์สถาปัตยกรรม ไลบรารี ViewModel คุณสามารถเข้าถึง ViewModel จาก Composable โดย การเรียกฟังก์ชัน viewModel() เพิ่มทรัพยากร Dependency ต่อไปนี้ลงในไฟล์ Gradle

ดึงดูด

dependencies {
    implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1'
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
}

จากนั้นคุณจะใช้ฟังก์ชัน viewModel() ในโค้ดได้

class MyViewModel : ViewModel() { /*...*/ }

// import androidx.lifecycle.viewmodel.compose.viewModel
@Composable
fun MyScreen(
    viewModel: MyViewModel = viewModel()
) {
    // use viewModel here
}

viewModel() จะแสดงผล ViewModel ที่มีอยู่หรือสร้างรายการใหม่ โดยค่าเริ่มต้น ViewModel ที่แสดงผลจะกำหนดขอบเขตเป็นกิจกรรม ส่วนย่อย หรือ ปลายทางการนำทาง และจะยังคงอยู่ตราบเท่าที่ขอบเขตยังใช้งานได้

ตัวอย่างเช่น หากใช้ Composable ในกิจกรรม viewModel() จะแสดงผลเมธอด อินสแตนซ์เดียวกันจนกว่ากิจกรรมจะเสร็จสิ้น หรือยกเลิกกระบวนการ

class MyViewModel : ViewModel() { /*...*/ }
// import androidx.lifecycle.viewmodel.compose.viewModel
@Composable
fun MyScreen(
    // Returns the same instance as long as the activity is alive,
    // just as if you grabbed the instance from an Activity or Fragment
    viewModel: MyViewModel = viewModel()
) { /* ... */ }

@Composable
fun MyScreen2(
    viewModel: MyViewModel = viewModel() // Same instance as in MyScreen
) { /* ... */ }

หลักเกณฑ์การใช้งาน

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

พยายามอย่าส่งต่อ ViewModel อินสแตนซ์ไปยัง Composable อื่น เนื่องจากสามารถทำให้ Composable เหล่านั้นได้ ยากต่อการทดสอบและอาจ ตัวอย่าง แต่ให้ส่งผ่านเฉพาะข้อมูล และฟังก์ชันที่จำเป็นเป็นพารามิเตอร์

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

หาก ViewModel มีทรัพยากร Dependency viewModel() จะใช้ตัวเลือกที่ไม่บังคับ ViewModelProvider.Factory เป็นพารามิเตอร์

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

สตรีมข้อมูล

Compose มาพร้อมกับส่วนขยายสำหรับโซลูชันที่ใช้สตรีมซึ่งเป็นที่นิยมมากที่สุดของ Android ส่วนขยายแต่ละรายการเหล่านี้มาจากอาร์ติแฟกต์ที่แตกต่างกันดังนี้

  • LiveData.observeAsState() รวมอยู่ในอาร์ติแฟกต์ androidx.compose.runtime:runtime-livedata:$composeVersion
  • Flow.collectAsState() ไม่ต้องการการอ้างอิงเพิ่มเติม
  • Observable.subscribeAsState() รวมอยู่ในอาร์ติแฟกต์ androidx.compose.runtime:runtime-rxjava2:$composeVersion หรือ androidx.compose.runtime:runtime-rxjava3:$composeVersion

สิ่งประดิษฐ์เหล่านี้จะลงทะเบียนเป็นผู้ฟังและแสดงถึงค่านิยมในฐานะ State เมื่อใดก็ตามที่ค่าใหม่ เขียนได้ Compose จะเขียนส่วนของ UI ใหม่ที่ state.value ถูก ตัวอย่างเช่น ในโค้ดนี้ ShowData จะเขียนใหม่ทุกครั้ง exampleLiveData จะแสดงค่าใหม่

// import androidx.lifecycle.viewmodel.compose.viewModel
@Composable
fun MyScreen(
    viewModel: MyViewModel = viewModel()
) {
    val dataExample = viewModel.exampleLiveData.observeAsState()

    // Because the state is read here,
    // MyScreen recomposes whenever dataExample changes.
    dataExample.value?.let {
        ShowData(dataExample)
    }
}

การดำเนินการแบบไม่พร้อมกันใน Compose

Jetpack Compose ให้คุณเรียกใช้การดำเนินการแบบไม่พร้อมกันโดยใช้ Coroutine จาก ใน Composable

ดู LaunchedEffect, produceState และ rememberCoroutineScope API ใน โปรดดูเอกสารประกอบของผลข้างเคียง

คอมโพเนนต์การนำทางจะรองรับแอปพลิเคชัน Jetpack Compose โปรดดูการไปยังส่วนต่างๆ ด้วยการเขียน และ ย้ายข้อมูลการนำทางใน Jetpack ไปยังฟีเจอร์ช่วยเขียนในการไปยังส่วนต่างๆ เพื่อดูข้อมูลเพิ่มเติม

ฮิลต์

Hilt เป็นโซลูชันที่แนะนำสำหรับการแทรกทรัพยากร Dependency ในแอป Android และ ใช้งาน Compose ได้อย่างราบรื่น

ฟังก์ชัน viewModel() ที่กล่าวถึงในส่วน ViewModel ใช้ ViewModel ที่ Hilt สร้างด้วย @HiltViewModel โดยอัตโนมัติ หมายเหตุ เราได้จัดเตรียมเอกสารที่มีข้อมูลเกี่ยวกับ ViewModel ของ Hilt แล้ว การผสานรวม

@HiltViewModel
class MyViewModel @Inject constructor(
    private val savedStateHandle: SavedStateHandle,
    private val repository: ExampleRepository
) : ViewModel() { /* ... */ }

// import androidx.lifecycle.viewmodel.compose.viewModel
@Composable
fun MyScreen(
    viewModel: MyViewModel = viewModel()
) { /* ... */ }

Hilt และการนำทาง

Hilt ยังผสานรวมเข้ากับไลบรารีการช่วยเขียนในการไปยังส่วนต่างๆ เพิ่มรายการต่อไปนี้ ทรัพยากร Dependency เพิ่มเติมในไฟล์ Gradle

ดึงดูด

dependencies {
    implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'
}

Kotlin

dependencies {
    implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
}

เมื่อใช้การเขียนในการนำทาง ให้ใช้ Composable hiltViewModel เสมอ เพื่อรับอินสแตนซ์ของ @HiltViewModel ที่มีคำอธิบายประกอบ ViewModel การดำเนินการนี้ใช้ได้กับส่วนย่อยหรือกิจกรรมที่มีคำอธิบายประกอบ @AndroidEntryPoint

ตัวอย่างเช่น หาก ExampleScreen เป็นจุดหมายในกราฟการนำทาง เรียกใช้ hiltViewModel() เพื่อรับอินสแตนซ์ของ ExampleViewModel ที่มีขอบเขต ไปยังปลายทางดังที่แสดงในข้อมูลโค้ดด้านล่าง

// import androidx.hilt.navigation.compose.hiltViewModel

@Composable
fun MyApp() {
    val navController = rememberNavController()
    val startRoute = "example"
    NavHost(navController, startDestination = startRoute) {
        composable("example") { backStackEntry ->
            // Creates a ViewModel from the current BackStackEntry
            // Available in the androidx.hilt:hilt-navigation-compose artifact
            val viewModel = hiltViewModel<MyViewModel>()
            MyScreen(viewModel)
        }
        /* ... */
    }
}

หากต้องการเรียกข้อมูลอินสแตนซ์ของ ViewModel ที่กำหนดขอบเขตเป็น เส้นทางการนำทาง หรือ กราฟการนำทาง ให้ใช้ฟังก์ชัน Composable hiltViewModel แทนและส่งค่าที่เกี่ยวข้อง backStackEntry เป็นพารามิเตอร์:

// import androidx.hilt.navigation.compose.hiltViewModel
// import androidx.navigation.compose.getBackStackEntry

@Composable
fun MyApp() {
    val navController = rememberNavController()
    val startRoute = "example"
    val innerStartRoute = "exampleWithRoute"
    NavHost(navController, startDestination = startRoute) {
        navigation(startDestination = innerStartRoute, route = "Parent") {
            // ...
            composable("exampleWithRoute") { backStackEntry ->
                val parentEntry = remember(backStackEntry) {
                    navController.getBackStackEntry("Parent")
                }
                val parentViewModel = hiltViewModel<ParentViewModel>(parentEntry)
                ExampleWithRouteScreen(parentViewModel)
            }
        }
    }
}

การแบ่งหน้า

การแบ่งหน้า คลัง จะช่วยให้คุณโหลดข้อมูลทีละน้อยได้ง่ายขึ้น และรองรับใน Compose การเปิดตัวเพจ page มี ข้อมูลเกี่ยวกับทรัพยากร Dependency เพิ่มเติมของ paging-compose ที่ต้องเพิ่ม กับโปรเจ็กต์และเวอร์ชันของโปรเจ็กต์

ต่อไปนี้คือตัวอย่าง Compose API ของไลบรารี Paging

@Composable
fun MyScreen(flow: Flow<PagingData<String>>) {
    val lazyPagingItems = flow.collectAsLazyPagingItems()
    LazyColumn {
        items(
            lazyPagingItems.itemCount,
            key = lazyPagingItems.itemKey { it }
        ) { index ->
            val item = lazyPagingItems[index]
            Text("Item is $item")
        }
    }
}

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

แผนที่

คุณสามารถใช้การเขียนของ Maps เพื่อให้บริการ Google Maps ในแอปของคุณ ตัวอย่างการใช้งานมีดังนี้

@Composable
fun MapsExample() {
    val singapore = LatLng(1.35, 103.87)
    val cameraPositionState = rememberCameraPositionState {
        position = CameraPosition.fromLatLngZoom(singapore, 10f)
    }
    GoogleMap(
        modifier = Modifier.fillMaxSize(),
        cameraPositionState = cameraPositionState
    ) {
        Marker(
            state = MarkerState(position = singapore),
            title = "Singapore",
            snippet = "Marker in Singapore"
        )
    }
}