W sekcji „Tworzenie” 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 spowoduje uruchomienie prośby. Lambda końcowa dla rememberLauncherForActivityResult()
jest wywoływana, gdy użytkownik wybierze obraz i wróci do aktywności uruchamiającej.
Spowoduje to załadowanie wybranego obrazu za pomocą funkcji rememberImagePainter()
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 systemowego przycisku Wstecz
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, a BackHandler
jest obecnie włączone.
ViewModel
Jeśli używasz biblioteki ViewModel Komponenty architektury, możesz uzyskać dostęp do modelu ViewModel
z dowolnego elementu kompozycyjnego, 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 element ViewModel
jest ograniczony do obejmującej go aktywności, fragmentu lub miejsca docelowego nawigacji 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
Zwykle uzyskujesz dostęp do instancji ViewModel
na poziomie funkcji kompozycyjnych na poziomie ekranu, czyli w pobliżu głównego elementu kompozycyjnego wywoływanego z działania, fragmentu lub miejsca docelowego 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 usługi 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 przekazuj w postaci parametrów
tylko potrzebne dane i funkcje.
Możesz używać instancji ViewModel
do zarządzania stanem elementów kompozycyjnych na poziomie ekranu podrzędnego, ale pamiętaj o cyklu życia i zakresie elementu ViewModel
. Jeśli funkcja kompozycyjna jest autonomiczna, możesz użyć Hilt, aby wstawić ViewModel
. Pozwoli to uniknąć przekazywania zależności od nadrzędnych funkcji kompozycyjnych.
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,
Usługa Compose zawiera rozszerzenia do najpopularniejszych rozwiązań na Androida korzystających ze strumieniowania. 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()
w artefakcieandroidx.compose.runtime:runtime-rxjava2:$composeVersion
lubandroidx.compose.runtime:runtime-rxjava3:$composeVersion
.
Te artefakty są rejestrowane jako detektor 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 używana jest zmienna state.value
. W tym kodzie na przykład ShowData
tworzy nową wartość za każdym razem, gdy exampleLiveData
generuje 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 funkcji tworzenia wiadomości
Jetpack Compose umożliwia wykonywanie operacji asynchronicznych za pomocą współrzędnych z poziomu kompozytora.
Więcej informacji znajdziesz w dokumentacji interfejsów API LaunchedEffect
, produceState
i rememberCoroutineScope
w dokumentacji poświęconej skutkom ubocznym.
Nawigacja
Komponent Nawigacja zapewnia obsługę aplikacji 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
.
Działa to we fragmentach lub działaniach oznaczonych adnotacją @AndroidEntryPoint
.
Jeśli na przykład ExampleScreen
jest celem w grafie nawigacji, wywołaj funkcję hiltViewModel()
, aby uzyskać instancję ExampleViewModel
ograniczoną do tego celu, 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 zamiast tego 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) } } } }
Strona
Biblioteka Paging ułatwia stopniowe wczytywanie danych i jest obsługiwana w Compose.
Strona wersji 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") } } }
Więcej informacji o używaniu stronicowania w tworzeniu wiadomości znajdziesz w dokumentacji list i siatek.
Mapy
Możesz użyć biblioteki Maps Compose, aby udostępnić Mapy Google w swojej aplikacji. 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 wyświetla się, gdy JavaScript jest wyłączony
- Efekty uboczne w edytorze
- Stan i Jetpack Compose
- Zapisywanie stanu interfejsu w narzędziu Compose