คุณสามารถใช้ไลบรารีโปรดใน Compose ได้ ส่วนนี้จะอธิบายวิธีรวมไลบรารีที่มีประโยชน์มากที่สุดบางส่วน
กิจกรรม
หากต้องการใช้ Compose ในกิจกรรม คุณต้องใช้
ComponentActivity,
ซึ่งเป็นคลาสย่อยของ Activity ที่มี LifecycleOwner และ
คอมโพเนนต์ที่เหมาะสมสำหรับ Compose นอกจากนี้ ยังมี API เพิ่มเติมที่แยกโค้ดของคุณออกจากการลบล้างเมธอดในคลาสกิจกรรม
Activity Compose
จะแสดง API เหล่านี้ต่อคอมโพสได้ เพื่อให้ไม่จำเป็นต้องลบล้างเมธอดนอก
คอมโพสหรือดึงข้อมูลอินสแตนซ์ Activity ที่ชัดเจนอีกต่อไป
นอกจากนี้ API เหล่านี้ยังช่วยให้มั่นใจได้ว่าจะมีการเริ่มต้นเพียงครั้งเดียว คงอยู่ได้แม้จะมีการคอมโพสใหม่ และล้างข้อมูลอย่างเหมาะสมหากนำคอมโพสออกจากคอมโพส
ผลลัพธ์ของกิจกรรม
API
rememberLauncherForActivityResult()
ช่วยให้คุณ
รับผลลัพธ์จากกิจกรรม
ในคอมโพสได้
@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 Permissions เป็นเลเยอร์เหนือ API เหล่านั้นเพื่อแมปสถานะที่ได้รับอนุญาตในปัจจุบัน สำหรับสิทธิ์ต่างๆ ลงในสถานะที่ UI ของ Compose ใช้ได้
การจัดการปุ่มย้อนกลับของระบบ
หากต้องการให้การนำทางย้อนกลับที่กำหนดเอง
และลบล้างลักษณะการทำงานเริ่มต้นของปุ่มย้อนกลับของระบบจากภายใน
คอมโพส คอมโพสสามารถใช้
BackHandler
เพื่อดักจับเหตุการณ์นั้นได้
var backHandlingEnabled by remember { mutableStateOf(true) } BackHandler(backHandlingEnabled) { // Handle back press }
อาร์กิวเมนต์แรกจะควบคุมว่าปัจจุบัน
BackHandler
เปิดใช้อยู่หรือไม่ คุณสามารถใช้อาร์กิวเมนต์นี้เพื่อปิดใช้ Handler ชั่วคราว
ตามสถานะของคอมโพเนนต์ ระบบจะเรียกใช้แลมบ์ดาต่อท้ายหากผู้ใช้ทริกเกอร์เหตุการณ์ย้อนกลับของระบบ และ
BackHandler
เปิดใช้อยู่
ViewModel
หากคุณใช้ไลบรารี Architecture Components
ViewModel คุณจะเข้าถึง
ViewModel จากคอมโพสใดก็ได้โดย
เรียกใช้ฟังก์ชัน
viewModel()
เพิ่มทรัพยากร Dependency ต่อไปนี้ลงในไฟล์ Gradle
ดึงดูด
dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0' }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.10.0") }
จากนั้นคุณจะใช้ฟังก์ชัน viewModel() ในโค้ดได้
class MyViewModel : ViewModel() { /*...*/ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { // use viewModel here }
viewModel() จะแสดงผล ViewModel ที่มีอยู่หรือสร้าง ViewModel ใหม่ โดยค่าเริ่มต้น ViewModel ที่แสดงผลจะมีขอบเขตเป็นกิจกรรม, Fragment หรือปลายทางการนำทางที่ล้อมรอบ และจะคงอยู่ตราบใดที่ขอบเขตยังคงอยู่
ตัวอย่างเช่น หากใช้คอมโพสในกิจกรรม 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 ที่คอมโพส ระดับหน้าจอ นั่นคือใกล้กับคอมโพสรากที่เรียกจากกิจกรรม, Fragment หรือปลายทางของกราฟการนำทาง เนื่องจากโดยค่าเริ่มต้น ViewModel จะมีขอบเขตเป็นออบเจ็กต์ ระดับหน้าจอ เหล่านั้น อ่านเพิ่มเติมเกี่ยวกับวงจรการทำงานและขอบเขตของ
ViewModel's
ได้ที่นี่
หลีกเลี่ยงการส่ง
ViewModelอินสแตนซ์ไปยังคอมโพสอื่นๆ เนื่องจากอาจทำให้คอมโพสเหล่านั้น
ทดสอบได้ยากขึ้นและอาจทำให้
การแสดงตัวอย่างใช้งานไม่ได้ ให้ส่งเฉพาะข้อมูลและฟังก์ชันที่คอมโพสเหล่านั้นต้องการเป็นพารามิเตอร์แทน
คุณ สามารถ ใช้คอมโพส ViewModel เพื่อ
จัดการสถานะสำหรับคอมโพส ระดับหน้าจอย่อย ได้ แต่โปรดทราบวงจรการทำงานและขอบเขตของ
ViewModel's
lifecycle and scope หากคอมโพสมีข้อมูลครบถ้วนในตัวเอง คุณอาจพิจารณาใช้ Hilt เพื่อแทรก ViewModel เพื่อหลีกเลี่ยงการส่งทรัพยากร Dependency จากคอมโพสระดับบน
หาก ViewModel มีทรัพยากร Dependency viewModel() จะใช้
ViewModelProvider.Factory
ที่ไม่บังคับเป็นพารามิเตอร์
ดูข้อมูลเพิ่มเติมเกี่ยวกับ ViewModel ใน Compose และวิธีใช้คอมโพสกับไลบรารีการนำทาง
หรือกิจกรรมและ Fragment
ได้ที่เอกสารประกอบเกี่ยวกับการทำงานร่วมกัน
สตรีมข้อมูล
Compose มาพร้อมกับส่วนขยายสำหรับโซลูชันที่อิงตามสตรีมที่ได้รับความนิยมมากที่สุดของ Android โดยอาร์ติแฟกต์ต่างๆ จะมีส่วนขยายแต่ละรายการต่อไปนี้
LiveData.observeAsState()รวมอยู่ในอาร์ติแฟกต์androidx.compose.runtime:runtime-livedata:$composeVersionFlow.collectAsState()ไม่ต้องใช้ทรัพยากร Dependency เพิ่มเติมObservable.subscribeAsState()รวมอยู่ในอาร์ติแฟกต์androidx.compose.runtime:runtime-rxjava2:$composeVersionหรือandroidx.compose.runtime:runtime-rxjava3:$composeVersion
อาร์ติแฟกต์เหล่านี้จะลงทะเบียนเป็น Listener และแสดงค่าเป็น
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 จากภายในคอมโพส
ดู API LaunchedEffect, produceState, และ rememberCoroutineScope ใน
เอกสารประกอบเกี่ยวกับผลข้างเคียงเพื่อดูข้อมูลเพิ่มเติม
การนำทาง
คอมโพเนนต์ การนำทาง รองรับแอปพลิเคชัน Jetpack Compose ดูข้อมูลเพิ่มเติมได้ที่ การนำทางด้วย Compose และ ย้ายข้อมูลการนำทาง Jetpack ไปยังการนำทาง Compose
Hilt
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 ยังผสานรวมกับไลบรารีการนำทาง Compose ด้วย เพิ่มทรัพยากร Dependency เพิ่มเติมต่อไปนี้ลงในไฟล์ Gradle
ดึงดูด
dependencies { implementation 'androidx.hilt:hilt-navigation-compose:1.3.0' }
Kotlin
dependencies { implementation("androidx.hilt:hilt-navigation-compose:1.3.0") }
เมื่อใช้การนำทาง Compose ให้ใช้ฟังก์ชันคอมโพส hiltViewModel เสมอเพื่อรับอินสแตนซ์ของ @HiltViewModel ที่มีคำอธิบายประกอบ ViewModel
ซึ่งใช้ได้กับ Fragment หรือกิจกรรมที่มีคำอธิบายประกอบ @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 ที่มีขอบเขตเป็น
เส้นทางการนำทาง หรือ กราฟการนำทาง
แทน ให้ใช้ฟังก์ชันที่ประกอบกันได้ 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 รองรับไลบรารีนี้
หน้าเผยแพร่เพจจิ้ง
มีข้อมูลเกี่ยวกับทรัพยากร Dependency paging-compose เพิ่มเติมที่ต้องเพิ่มลงในโปรเจ็กต์และเวอร์ชันของทรัพยากร Dependency ดังกล่าว
ตัวอย่าง API ของไลบรารีเพจจิ้งสำหรับ Compose
@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
คุณสามารถใช้ไลบรารี Maps Compose เพื่อแสดง 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 = remember { MarkerState(position = singapore) }, title = "Singapore", snippet = "Marker in Singapore" ) } }
แนะนำสำหรับคุณ
- หมายเหตุ: ข้อความลิงก์จะแสดงเมื่อ JavaScript ปิดอยู่
- ผลข้างเคียงใน Compose
- สถานะและ Jetpack Compose
- บันทึกสถานะ UI ใน Compose