คุณใช้คลังเพลงโปรดใน "เขียน" ได้ ส่วนนี้จะอธิบายวิธีใช้ไลบรารีที่มีประโยชน์ที่สุด 2-3 รายการ
กิจกรรม
หากต้องการใช้ Compose ในกิจกรรม คุณต้องใช้ ComponentActivity
ซึ่งเป็นคลาสย่อยของ Activity
ที่ให้ LifecycleOwner
และคอมโพเนนต์ที่เหมาะสมกับ Compose และยังให้บริการ API เพิ่มเติมที่แยกโค้ดของคุณออกจากการลบล้างเมธอดในคลาสกิจกรรม
Activity Compose จะแสดง API เหล่านี้ต่อคอมโพสิเบิลต่างๆ เพื่อที่คุณจะได้ไม่ต้องเขียนเมธอดที่ลบล้างนอกคอมโพสิเบิลหรือดึงข้อมูลอินสแตนซ์ Activity
อย่างชัดเจนอีกต่อไป
นอกจากนี้ API เหล่านี้ยังช่วยดูแลให้ API มีการเริ่มต้นเพียงครั้งเดียว คงอยู่ใหม่ และล้างข้อมูลได้อย่างถูกต้องหาก Composable ถูกนำออกจากการเรียบเรียง
ผลลัพธ์ของกิจกรรม
rememberLauncherForActivityResult()
API นี้ช่วยให้คุณรับผลลัพธ์จากกิจกรรมในคอมโพสิเบิลได้ ดังนี้
@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()
สัญญาที่เรียบง่าย การแตะปุ่มจะเป็นการเปิดคําขอ ระบบจะเรียกใช้ Lambda ต่อท้ายสำหรับ rememberLauncherForActivityResult()
เมื่อผู้ใช้เลือกรูปภาพและกลับไปที่กิจกรรมการเปิดใช้งาน
ซึ่งจะโหลดรูปภาพที่เลือกโดยใช้rememberImagePainter()
ฟังก์ชันของ Coil
คลาสย่อยของ ActivityResultContract
จะใช้เป็นอาร์กิวเมนต์แรกของ rememberLauncherForActivityResult()
ได้
ซึ่งหมายความว่าคุณสามารถใช้เทคนิคนี้เพื่อขอเนื้อหาจากเฟรมเวิร์กและในรูปแบบทั่วไปอื่นๆ ได้ นอกจากนี้ คุณยังสร้างสัญญาที่กําหนดเองและใช้กับเทคนิคนี้ได้อีกด้วย
การขอสิทธิ์รันไทม์
คุณสามารถใช้ Activity Result API และ rememberLauncherForActivityResult()
เดียวกันที่อธิบายไว้ด้านบนเพื่อขอสิทธิ์รันไทม์โดยใช้สัญญาสำหรับสิทธิ์เดียวหรือสัญญาสำหรับสิทธิ์หลายรายการก็ได้ โดยRequestPermission
RequestMultiplePermissions
นอกจากนี้ ไลบรารีสิทธิ์ของ Accompanist ยังใช้เลเยอร์เหนือ API เหล่านั้นเพื่อจับคู่สถานะการให้สิทธิ์ปัจจุบันสำหรับสิทธิ์ไว้ในสถานะที่ Compose UI ใช้ได้
การจัดการปุ่มย้อนกลับของระบบ
หากต้องการให้การนําทางกลับที่กําหนดเองและลบล้างลักษณะการทํางานเริ่มต้นของปุ่มย้อนกลับของระบบจากภายในคอมโพสิเบิล คอมโพสิเบิลของคุณสามารถใช้ BackHandler
เพื่อขัดจังหวะเหตุการณ์ดังกล่าว ดังนี้
var backHandlingEnabled by remember { mutableStateOf(true) } BackHandler(backHandlingEnabled) { // Handle back press }
อาร์กิวเมนต์แรกควบคุมว่า BackHandler
เปิดใช้อยู่หรือไม่ โดยคุณสามารถใช้อาร์กิวเมนต์นี้เพื่อปิดใช้เครื่องจัดการชั่วคราวตามสถานะของคอมโพเนนต์ ระบบจะเรียกใช้ Lambda ต่อท้ายหากผู้ใช้เรียกเหตุการณ์การกลับไปยังระบบ และBackHandler
เปิดใช้งานอยู่
ViewModel
หากใช้ไลบรารี Architecture Components
ViewModel คุณจะเข้าถึง ViewModel
จากคอมโพสิเบิลใดก็ได้โดยเรียกใช้ฟังก์ชัน viewModel()
เพิ่ม Dependency ต่อไปนี้ลงในไฟล์ Gradle
ดึงดูด
dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5' }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5") }
จากนั้นจึงใช้ฟังก์ชัน viewModel()
ในโค้ดได้
class MyViewModel : ViewModel() { /*...*/ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { // use viewModel here }
viewModel()
จะแสดง ViewModel
ที่มีอยู่หรือสร้าง ViewModel
ใหม่ โดยค่าเริ่มต้น ViewModel
ที่แสดงผลจะมีขอบเขตเป็นกิจกรรม ส่วนที่ฝัง หรือปลายทางการนําทางที่กําหนด และระบบจะเก็บไว้ตราบใดที่ขอบเขตยังมีอยู่
ตัวอย่างเช่น หากใช้คอมโพสิเบิลในกิจกรรม 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 ในระดับหน้าจอ ซึ่งอยู่ใกล้กับรูทที่ Composable ซึ่งเรียกจากกิจกรรม ส่วนย่อย หรือปลายทางของกราฟการนำทาง เนื่องจากโดยค่าเริ่มต้น ViewModel
s
จะมีขอบเขตที่จำกัดไว้สำหรับออบเจ็กต์ระดับหน้าจอเหล่านั้น อ่านข้อมูลเพิ่มเติมเกี่ยวกับวงจรและขอบเขตของViewModel
ได้ที่นี่
พยายามหลีกเลี่ยงการส่งต่ออินสแตนซ์ ViewModel
ไปยัง Composable อื่น เนื่องจากอาจทำให้ทดสอบ Composable เหล่านั้นได้ยากขึ้น และอาจทำให้ตัวอย่างเสียหาย แต่ให้ส่งเฉพาะข้อมูลและฟังก์ชันที่จำเป็นเป็นพารามิเตอร์แทน
คุณสามารถใช้อินสแตนซ์ ViewModel
เพื่อจัดการสถานะสำหรับคอมโพสิเบิลระดับหน้าจอย่อยได้ แต่โปรดคำนึงถึงวงจรและขอบเขตของ ViewModel
หากคอมโพสิเบิลมีทุกอย่างครบถ้วนแล้ว คุณอาจพิจารณาใช้ Hilt เพื่อแทรก ViewModel
เพื่อหลีกเลี่ยงการส่งข้อมูล Dependency จากคอมโพสิเบิลหลัก
หาก ViewModel
มีการขึ้นต่อกัน viewModel()
จะใช้พารามิเตอร์ ViewModelProvider.Factory
แบบไม่บังคับ
ดูข้อมูลเพิ่มเติมเกี่ยวกับ ViewModel
ใน Compose และวิธีใช้งานอินสแตนซ์กับไลบรารีของ 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 จากภายในคอมโพสิเบิล
ดูข้อมูลเพิ่มเติมเกี่ยวกับ API LaunchedEffect
, produceState
และ rememberCoroutineScope
ได้ในเอกสารประกอบเกี่ยวกับผลข้างเคียง
การไปยังรายการต่างๆ
คอมโพเนนต์การนำทางรองรับแอปพลิเคชัน Jetpack Compose ดูข้อมูลเพิ่มเติมที่การไปยังส่วนต่างๆ ด้วย Compose และย้ายข้อมูลการไปยังส่วนต่างๆ ของ Jetpack ไปยัง Navigation Compose
ฮิลต์
Hilt เป็นโซลูชันที่แนะนำสำหรับการฉีดข้อมูลในแอป 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 ยังผสานรวมกับไลบรารี Navigation Compose ด้วย เพิ่มทรัพยากร Dependency เพิ่มเติมต่อไปนี้ลงในไฟล์ Gradle
Groovy
dependencies { implementation 'androidx.hilt:hilt-navigation-compose:1.2.0' }
Kotlin
dependencies { implementation("androidx.hilt:hilt-navigation-compose:1.2.0") }
เมื่อใช้ Navigation Compose ให้ใช้ฟังก์ชัน hiltViewModel
composable
เสมอเพื่อรับอินสแตนซ์ของ @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
ที่มีขอบเขตเป็นเส้นทางการนําทางหรือกราฟการนําทางแทน ให้ใช้ฟังก์ชันคอมโพสิเบิล 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
หน้าการแยกหน้าของรุ่นมีข้อมูลเกี่ยวกับ paging-compose
เพิ่มเติมที่ต้องเพิ่มลงในโปรเจ็กต์และเวอร์ชันของโปรเจ็กต์
ต่อไปนี้คือตัวอย่าง Compose API ของไลบรารีการแบ่งหน้า
@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 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
- State และ Jetpack Compose
- บันทึกสถานะ UI ใน Compose