您可以在 Compose 中使用您喜欢的库。本节介绍如何合并一些最实用的库。
活动
要在活动中使用 Compose,您必须使用 ComponentActivity
,它是 Activity
的子类,它为 Compose 提供了适当的 LifecycleOwner
和组件。它还提供额外的 API,使您的代码与覆盖活动类中的方法分离。 活动 Compose 将这些 API 公开给可组合函数,因此不再需要在可组合函数之外覆盖方法或检索显式 Activity
实例。此外,这些 API 确保它们只初始化一次,在重新组合后保留,并在可组合函数从组合中移除时正确清理。
活动结果
该 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()
合同。点击按钮启动请求。该 rememberLauncherForActivityResult()
的尾部 lambda 在用户选择图像并返回到启动活动后被调用。这将使用 Coil 的 rememberImagePainter()
函数加载选定的图像。
任何 ActivityResultContract
的子类都可以用作 rememberLauncherForActivityResult()
的第一个参数。这意味着您可以使用此技术从框架和在其他常见模式中请求内容。您还可以创建自己的 自定义合同 并将它们与此技术一起使用。
请求运行时权限
上面解释的相同活动结果 API 和 rememberLauncherForActivityResult()
可以用来 请求运行时权限 使用 RequestPermission
合同用于单个权限或 RequestMultiplePermissions
合同用于多个权限。
该 Accompanist 权限库 也可以用作这些 API 之上的一个层,将权限的当前授予状态映射到 Compose UI 可以使用的状态。
处理系统后退按钮
要 提供自定义后退导航 并覆盖系统后退按钮从您的可组合函数内的默认行为,您的可组合函数可以使用 BackHandler
来拦截该事件
var backHandlingEnabled by remember { mutableStateOf(true) } BackHandler(backHandlingEnabled) { // Handle back press }
第一个参数控制 BackHandler
当前是否启用;您可以使用此参数根据组件的状态临时禁用处理程序。如果用户触发系统后退事件,并且 BackHandler
当前已启用,则会调用尾部 lambda。
视图模型
如果您使用 架构组件视图模型 库,您可以通过调用 viewModel()
函数从任何可组合函数访问 ViewModel
。将以下依赖项添加到您的 Gradle 文件中
Groovy
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
实例,即靠近从活动、片段或导航图的目的地调用的根可组合函数。这是因为 ViewModel
默认情况下,其范围限定为这些屏幕级对象。阅读有关 ViewModel
的 生命周期和范围的更多信息。
尝试避免将 ViewModel
实例向下传递给其他可组合函数,因为这会使这些可组合函数更难测试,并且会导致 预览 出现故障。相反,只将他们需要的参数和函数作为参数传递。
您可以使用 ViewModel
实例来管理子屏幕级可组合函数的状态,但是请注意 ViewModel
的 生命周期和范围。如果可组合函数是自包含的,您可能希望考虑使用 Hilt 来注入 ViewModel
,以避免必须从父可组合函数传递依赖项。
如果您的 ViewModel
有依赖项,viewModel()
接受一个可选的 ViewModelProvider.Factory
作为参数。
有关 Compose 中 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 就会重新组合使用该 state.value
的 UI 部分。例如,在此代码中,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 允许您使用协程从可组合函数内部执行异步操作。
有关更多信息,请参阅 副作用文档 中的 LaunchedEffect
、produceState
和 rememberCoroutineScope
API。
导航
该 导航组件 为 Jetpack Compose 应用程序提供支持。有关更多信息,请参阅 使用 Compose 导航 和 将 Jetpack Navigation 迁移到 Navigation Compose。
Hilt
Hilt 是 Android 应用程序中推荐的依赖项注入解决方案,并且与 Compose 无缝协作。
该 视图模型部分 中提到的 viewModel()
函数自动使用 Hilt 使用 @HiltViewModel
注释构建的视图模型。我们提供了有关 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 库集成。将以下附加依赖项添加到您的 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
可组合函数获取 @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 中使用分页的更多信息,请查看 列表和网格文档。
地图
您可以使用 地图 Compose 库在您的应用程序中提供 Google 地图。以下是一个使用示例
@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" ) } }
为您推荐
- 注意:当 JavaScript 关闭时,链接文本将显示
- Compose 中的副作用
- 状态和 Jetpack Compose
- 在 Compose 中保存 UI 状态