您可以在 Compose 中使用自己偏好的程式庫。本節將說明如何加入一些最為實用的程式庫。
Activity
如要在活動中使用 Compose,您必須使用 ComponentActivity
,這是 Activity
的子類別,可向 Compose 提供適當的 LifecycleOwner
和元件。該類別還可提供其他 API,以便將程式碼與活動類別的覆寫方法分離。Activity Compose 會將向可組合項公開這些 API,這樣您就無需覆寫可組合項之外的方法,或是擷取明確的 Activity
執行個體。此外,這些 API 可確保只需將其初始化一次,在重構後仍有效,並且可在從組合內容中移除可組合項後妥善清理。
Activity 結果
rememberLauncherForActivityResult()
API 可讓您從可組合項取得 Activity 結果:
@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()
合約。輕觸按鈕即可啟動要求。使用者選取圖片並返回正在啟動的 Activity 後,系統就會叫用 rememberLauncherForActivityResult()
的結尾 lambda。這個指令會使用 Coil 的 rememberImagePainter()
函式載入所選圖片。
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
;您可以根據元件狀態使用此引數暫時停用處理常式。如果使用者觸發系統返回事件,且目前已啟用 BackHandler
,則系統會叫用結尾 lambda。
ViewModel
如果您使用架構元件 ViewModel 程式庫,可以呼叫 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()
會傳回相同的例項,直到活動完成或程序結束為止。
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
,以及如何將執行個體與 Navigation Compose 程式庫或活動和片段搭配使用,請參閱互通性說明文件。
資料串
Compose 帶有擴充功能,適用於 Android 最熱門的串流式解決方案。這些擴充功能均由不同的構件提供:
androidx.compose.runtime:runtime-livedata:$composeVersion
構件中包含LiveData.observeAsState()
。Flow.collectAsState()
不需要額外的依附元件。androidx.compose.runtime:runtime-rxjava2:$composeVersion
或androidx.compose.runtime:runtime-rxjava3:$composeVersion
構件中包含Observable.subscribeAsState()
。
這些構件會註冊為事件監聽器,並顯示值為 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 可助您透過可組合項中的協同程式執行非同步作業。
詳情請參閱副作用說明文件中的 LaunchedEffect
、produceState
和 rememberCoroutineScope
API。
導覽
Navigation 元件可支援 Jetpack Compose 應用程式。詳情請參閱「使用 Compose 進行導覽」和「將 Jetpack Navigation 遷移至 Navigation Compose」。
Hilt
我們建議您在向 Android 應用程式插入依附元件時採用 Hilt 解決方案,並且 Hilt 可與 Compose 完美搭配運作。
ViewModel 部分中提及的 viewModel()
函式會自動採用 Hilt 透過 @HiltViewModel
註解建構的 ViewModel。我們在說明文件中提供了 Hilt 的 ViewModel 整合相關資訊。
@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 與 Navigation
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
註解的 Fragment 或 Activity 搭配使用。
例如,如果 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
您可以使用 Maps 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 = remember { MarkerState(position = singapore) }, title = "Singapore", snippet = "Marker in Singapore" ) } }
為您推薦
- 注意:系統會在 JavaScript 關閉時顯示連結文字
- Compose 中的連帶效果
- 狀態和 Jetpack Compose
- 在 Compose 中儲存 UI 狀態