W sekcji „Utwórz” możesz korzystać z ulubionych bibliotek. Z tej sekcji dowiesz się, jak włączyć kilka najprzydatniejszych bibliotek.
Aktywność
Aby użyć Compose w aktywności, musisz użyć klasy ComponentActivity
, która jest podklasą klasy Activity
i zawiera odpowiednie komponenty LifecycleOwner
do Compose. Udostępnia też dodatkowe interfejsy API, które odłączają kod od zastępowania metod w klasie aktywności.
Activity Compose udostępnia te interfejsy API komponentom, dzięki czemu nie trzeba już zastępować metod poza komponentami ani pobierać jawnej instancji Activity
.
Ponadto te interfejsy API zapewniają, że są inicjowane tylko raz, przetrwają rekompozycję i zostają prawidłowo usunięte, jeśli kompozyt został usunięty z kompozycji.
Wynik aktywności
Interfejs API rememberLauncherForActivityResult()
umożliwia uzyskanie wyniku z działalności w komponowalnym:
@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" ) } }
Ten przykład pokazuje prosty GetContent()
kontrakt. Kliknięcie przycisku powoduje wysłanie prośby. Lambda końcowa dla rememberLauncherForActivityResult()
jest wywoływana, gdy użytkownik wybierze obraz i powróci do aktywności uruchamiającej.
Spowoduje to załadowanie wybranego obrazu za pomocą funkcji rememberImagePainter()
w Coil.
Jako pierwszy argument funkcji rememberLauncherForActivityResult()
można użyć dowolnej podklasy typu ActivityResultContract
.
Oznacza to, że możesz użyć tej techniki, aby poprosić o treści z ramy, a także w innych typowych wzorach. Możesz też tworzyć własne kontrakty niestandardowe i stosować je za pomocą tej metody.
Wysyłanie prośby o uprawnienia w czasie działania
Tego samego interfejsu Activity Result API i rememberLauncherForActivityResult()
, o których mowa powyżej, można używać do wysyłania żądań uprawnień na czas działania, korzystając z RequestPermission
uprawnień dla pojedynczego uprawnienia lub RequestMultiplePermissions
uprawnień dla wielu uprawnień.
Bibliotekę Accompanist Permissions można też używać jako warstwy nad tymi interfejsami API, aby mapować bieżący stan uprawnień na stan, którego może używać interfejs użytkownika Compose.
Obsługa przycisku Wstecz systemu
Aby zapewnić niestandardową nawigację wstecz i zastąpić domyślne zachowanie przycisku Wstecz w systemie, komponent może użyć elementu BackHandler
, aby przechwycić to zdarzenie:
var backHandlingEnabled by remember { mutableStateOf(true) } BackHandler(backHandlingEnabled) { // Handle back press }
Pierwszy argument określa, czy moduł BackHandler
jest obecnie włączony. Możesz użyć tego argumentu, aby tymczasowo wyłączyć moduł obsługi na podstawie stanu komponentu. Lambda końcowa zostanie wywołana, jeśli użytkownik wywoła zdarzenie systemowe wsteczne, a BackHandler
jest obecnie włączone.
ViewModel
Jeśli używasz biblioteki Architecture Components
ViewModel, możesz uzyskać dostęp do ViewModel
z dowolnego komponentu, wywołując funkcję
viewModel()
. Dodaj do pliku Gradle te zależności:
Groovy
dependencies { implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5' }
Kotlin
dependencies { implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.5") }
Następnie możesz użyć w kodze funkcji viewModel()
.
class MyViewModel : ViewModel() { /*...*/ } // import androidx.lifecycle.viewmodel.compose.viewModel @Composable fun MyScreen( viewModel: MyViewModel = viewModel() ) { // use viewModel here }
viewModel()
zwraca istniejący element ViewModel
lub tworzy nowy. Domyślnie zwracany parametr ViewModel
jest ograniczony do aktywności, fragmentu lub miejsca docelowego nawigacji, które je otaczają, i jest przechowywany tak długo, jak długo istnieje zakres.
Jeśli na przykład kompozyt jest używany w aktywności, viewModel()
zwraca tę samą instancję do czasu zakończenia aktywności lub zakończenia procesu.
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 ) { /* ... */ }
Wytyczne dotyczące użytkowania
Zazwyczaj dostęp do instancji ViewModel
uzyskujesz na poziomie ekranu, czyli w pobliżu głównego komponentu wywoływanego z aktywności, fragmentu lub miejsca docelowego w grafu nawigacji. Dzieje się tak, ponieważ ViewModel
są domyślnie ograniczone do tych obiektów na poziomie ekranu. Dowiedz się więcej o cyklu życia i zakresie ViewModel
.
Staraj się nie przekazywać instancji ViewModel
innym elementom składanym, ponieważ może to utrudnić ich testowanie i spowodować problemy z podglądem. Zamiast tego jako parametrów podawaj tylko dane i funkcje, których te dane potrzebują.
Możesz używać instancji ViewModel
do zarządzania stanem komponentów na poziomie podrzędnego ekranu, pamiętaj jednak o cyklu życia i zakresie komponenta ViewModel
. Jeśli kompozyt jest samowystarczalny, warto użyć Hilt do wstrzyknięcia ViewModel
, aby uniknąć przekazywania zależności z kompozytów nadrzędnych.
Jeśli funkcja ViewModel
ma zależności, funkcja viewModel()
przyjmuje opcjonalny parametr ViewModelProvider.Factory
.
Więcej informacji o komponencie ViewModel
w Compose oraz o tym, jak używać instancji z biblioteką Compose nawigacji lub aktywności i fragmentów znajdziesz w dokumentacji dotyczącej interoperacyjności.
strumienie danych,
Compose zawiera rozszerzenia dla najpopularniejszych na Androidzie rozwiązań opartych na strumieniu. Każde z tych rozszerzeń jest dostarczane w ramach innego artefaktu:
LiveData.observeAsState()
zawarte w artefakcieandroidx.compose.runtime:runtime-livedata:$composeVersion
.Flow.collectAsState()
nie wymaga dodatkowych zależności.Observable.subscribeAsState()
zawarty w artefakcieandroidx.compose.runtime:runtime-rxjava2:$composeVersion
lubandroidx.compose.runtime:runtime-rxjava3:$composeVersion
.
Te elementy rejestrują się jako słuchacze i reprezentują wartości jako State
. Za każdym razem, gdy zostanie wyemitowana nowa wartość, Compose ponownie skompiluje te części interfejsu, w których jest używana zmienna state.value
. Na przykład w tym kodzie funkcja ShowData
jest ponownie wykonywana za każdym razem, gdy funkcja exampleLiveData
wyemituje nową wartość.
// 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) } }
Operacje asynchroniczne w sekcji Compose
Jetpack Compose umożliwia wykonywanie operacji asynchronicznych za pomocą coroutines w ramach komponentów.
Więcej informacji znajdziesz w dokumentacji interfejsów API LaunchedEffect
, produceState
i rememberCoroutineScope
w dokumentacji poświęconej skutkom ubocznym.
Nawigacja
Komponent Nawigacja obsługuje aplikacje Jetpack Compose. Więcej informacji znajdziesz w artykule Przechodzenie między elementami za pomocą Compose i Przenoszenie nawigacji Jetpacka do Compose.
Hilt
Hilt to zalecane rozwiązanie do wstrzykiwania zależności w aplikacjach na Androida. Działa ono bezproblemowo z Compose.
Funkcja viewModel()
wymieniona w sekcji ViewModel automatycznie używa ViewModel utworzonego przez Hilt za pomocą adnotacji @HiltViewModel
. Udostępniliśmy dokumentację z informacjami o integracji Hilt z 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 i Nawigacja
Hilt integruje się też z biblioteką Navigation Compose. Dodaj do pliku Gradle te dodatkowe zależności:
Groovy
dependencies { implementation 'androidx.hilt:hilt-navigation-compose:1.2.0' }
Kotlin
dependencies { implementation("androidx.hilt:hilt-navigation-compose:1.2.0") }
Podczas korzystania z komponentu Nawigacja zawsze używaj funkcji hiltViewModel
, aby uzyskać instancję @HiltViewModel
z annotacjami ViewModel
.
Ta funkcja działa w przypadku fragmentów lub działań oznaczonych znacznikiem @AndroidEntryPoint
.
Jeśli na przykład ExampleScreen
to punkt docelowy w grafie nawigacji, wywołaj funkcję hiltViewModel()
, aby uzyskać instancję ExampleViewModel
ograniczoną do punktu docelowego, jak pokazano w tym fragmencie kodu:
// 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) } /* ... */ } }
Jeśli chcesz pobrać instancję funkcji ViewModel
ograniczoną do tras nawigacyjnych lub grafu nawigacyjnego, użyj funkcji składanej hiltViewModel
i przekaż jako parametr odpowiednią funkcję 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) } } } }
Paging
Biblioteka Paging ułatwia stopniowe wczytywanie danych i jest obsługiwana w Compose.
Strona wersji strony zawiera informacje o dodatkowej zależności paging-compose
, którą należy dodać do projektu i jego wersji.
Oto przykład interfejsów Compose biblioteki 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") } } }
Aby dowiedzieć się więcej o używaniu pagingu w Compose, zapoznaj się z dokumentacją dotyczącą list i kratek.
Mapy
Aby udostępnić Mapy Google w aplikacji, możesz użyć biblioteki Mapy – Compose. Oto przykład użycia:
@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" ) } }
Polecane dla Ciebie
- Uwaga: tekst linku jest wyświetlany, gdy obsługa JavaScript jest wyłączona
- Efekty uboczne w edytorze
- Stan i Jetpack Compose
- Zapisywanie stanu interfejsu w sekcji Utwórz