Compose und andere Bibliotheken

In „Compose“ können Sie Ihre bevorzugten Bibliotheken verwenden. In diesem Abschnitt wird beschrieben, wie Sie einige der nützlichsten Bibliotheken integrieren.

Aktivität

Um das Schreiben in einer Aktivität zu verwenden, müssen Sie ComponentActivity, Eine abgeleitete Klasse von Activity, die die entsprechenden LifecycleOwner- und für „Compose“. Außerdem bietet es zusätzliche APIs, die Ihren Code entkoppeln Methoden in Ihrer Aktivitätsklasse zu verhindern. Aktivität verfassen diese APIs zusammensetzbaren Funktionen zur Verfügung stellen, sodass das Überschreiben von Methoden außerhalb Ihres zusammensetzbare Funktionen oder das Abrufen einer expliziten Activity-Instanz sind nicht mehr erforderlich. Darüber hinaus stellen diese APIs sicher, dass sie nur einmal initialisiert werden, Zusammensetzung und saubere Inhalte entfernen, wenn die zusammensetzbare Funktion aus der Zusammensetzung.

Aktivitätsergebnis

Die rememberLauncherForActivityResult() API ermöglicht Ihnen Folgendes: Ergebnis aus einer Aktivität abrufen in der zusammensetzbaren Funktion:

@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"
        )
    }
}

Dieses Beispiel zeigt ein einfaches GetContent() Vertrag. Durch Tippen auf die Schaltfläche wird die Anfrage gestartet. Das nachgestellte Lambda für rememberLauncherForActivityResult() wird aufgerufen, sobald der Benutzer ein Image auswählt und zur Startaktivität zurückkehrt. Dadurch wird das ausgewählte Bild mit dem rememberImagePainter() von Coil geladen .

Jede abgeleitete Klasse von ActivityResultContract kann als erstes Argument verwendet werden, rememberLauncherForActivityResult() Sie können also mit dieser Technik Inhalte aus dem Framework anfordern. und in anderen gängigen Mustern. Sie können auch Ihre eigenen kundenspezifischen Verträgen und verwenden Sie mit dieser Technik.

Laufzeitberechtigungen anfordern

Dieselbe Activity Result API und rememberLauncherForActivityResult() wie oben beschrieben, können Laufzeitberechtigungen anfordern mithilfe der RequestPermission für eine einzige Genehmigung oder RequestMultiplePermissions für mehrere Berechtigungen.

Die Accompanist Permissions Library kann auch eine Ebene über diesen APIs verwendet werden, um den aktuell erteilten Status auf „Status“ gesetzt, die Ihre Benutzeroberfläche zum Schreiben verwenden kann.

Umgang mit der Zurück-Schaltfläche des Systems

Um eine benutzerdefinierte Rückwärtsnavigation bereitzustellen und das Standardverhalten der Zurück-Schaltfläche des Systems zusammensetzbar ist, kann Ihre zusammensetzbare Funktion BackHandler um dieses Ereignis abzufangen:

var backHandlingEnabled by remember { mutableStateOf(true) }
BackHandler(backHandlingEnabled) {
    // Handle back press
}

Das erste Argument steuert, BackHandler ist derzeit aktiviert. können Sie mit diesem Argument den Handler vorübergehend deaktivieren. basierend auf dem Status Ihrer Komponente. Das nachgestellte Lambda wird aufgerufen, wenn die ein System-Back-Ereignis auslöst und der BackHandler ist derzeit aktiviert.

ViewModel

Bei Verwendung der Architekturkomponenten ViewModel-Bibliothek ansehen, können Sie auf ViewModel aus einer beliebigen zusammensetzbaren Funktion mit das Aufrufen der viewModel() . Fügen Sie Ihrer Gradle-Datei die folgende Abhängigkeit hinzu:

Cool

dependencies {
    implementation 'androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1'
}

Kotlin

dependencies {
    implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.6.1")
}

Anschließend können Sie die Funktion viewModel() in Ihrem Code verwenden.

class MyViewModel : ViewModel() { /*...*/ }

// import androidx.lifecycle.viewmodel.compose.viewModel
@Composable
fun MyScreen(
    viewModel: MyViewModel = viewModel()
) {
    // use viewModel here
}

viewModel() gibt ein vorhandenes ViewModel zurück oder erstellt ein neues. Standardmäßig ist die zurückgegebene ViewModel auf die einschließende Aktivität, das Fragment oder Navigationsziel und bleiben erhalten, solange der Bereich aktiv ist.

Wird die zusammensetzbare Funktion beispielsweise in einer Aktivität verwendet, gibt viewModel() den Fehlerwert bis die Aktivität abgeschlossen oder der Prozess beendet wird.

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
) { /* ... */ }

Nutzungsrichtlinien

Normalerweise greifen Sie auf ViewModel Instanzen auf Bildschirmebene zu zusammensetzbar, also nahe an einer zusammensetzbaren Stammfunktion, die aus einer Aktivität aufgerufen wird, Fragment oder Ziel eines Navigationsdiagramms. Grund: ViewModel sind standardmäßig diesen Objekten auf Bildschirmebene zugeordnet. Weitere Informationen zu einem ViewModel Lebenszyklus und Umfang.

Vermeide dein Überleben ViewModel-Instanzen zu anderen zusammensetzbaren Funktionen hinzufügen, da dies diese zusammensetzbaren Funktionen erstellen kann. schwieriger zu testen ist und Vorschauen aufrufen. Stattdessen werden nur die Daten und Funktionen, die sie als Parameter benötigen.

Sie können ViewModel-Instanzen für Folgendes verwenden: den Status für zusammensetzbare Funktionen auf untergeordneten Bildschirmebene verwalten. Beachten Sie jedoch die ViewModel Lebenszyklus und Umfang. Wenn die ist eigenständig. Mit Hilt können Sie ViewModel einschleusen, damit keine Abhängigkeiten vom übergeordneten Element übergeben werden müssen zusammensetzbare Funktionen verwenden.

Wenn Ihre ViewModel Abhängigkeiten enthält, verwendet viewModel() einen optionalen ViewModelProvider.Factory als Parameter verwendet werden.

Weitere Informationen zu ViewModel in Compose und zur Verwendung von Instanzen „Navigation Compose-Bibliothek“ oder Aktivitäten und Fragmente Weitere Informationen finden Sie in der Interoperabilitätsdokumentation.

Datenstreams

Compose enthält Erweiterungen für die beliebtesten streambasierten Android-Lösungen. Jede dieser Erweiterungen wird von einem anderen Artefakt bereitgestellt:

Diese Artefakte werden als Listener registriert und stellen die Werte als State Wenn ein neuer Wert ausgegeben wird, setzt „Compose“ die Teile der UI neu zusammen, in denen sich state.value befindet verwendet. In diesem Code wird ShowData beispielsweise jedes Mal neu zusammengesetzt. „exampleLiveData“ gibt einen neuen Wert aus.

// 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)
    }
}

Asynchrone Vorgänge in „Compose“

Mit Jetpack Compose können Sie asynchrone Vorgänge mit Koroutinen aus in den zusammensetzbaren Funktionen.

Die APIs LaunchedEffect, produceState und rememberCoroutineScope finden Sie in Weitere Informationen finden Sie in der Dokumentation zu Nebeneffekten. Informationen.

Die Navigationskomponente bietet Unterstützung für Jetpack Compose-Anwendungen. Weitere Informationen finden Sie unter Navigation mit dem Editor und Weitere Informationen finden Sie unter Jetpack Navigation zu Navigation Compose migrieren.

Griff

Hilt ist die empfohlene Lösung für das Einschleusen von Abhängigkeiten in Android-Apps. mit der Funktion „Schreiben“.

Die im Abschnitt „ViewModel“ erwähnte Funktion viewModel() verwendet automatisch das ViewModel, das Hilt mit der @HiltViewModel erstellt. . Die Dokumentation enthält Informationen zum ViewModel von 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()
) { /* ... */ }

Griff und Navigation

Hilt ist auch in die Navigation Compose-Bibliothek integriert. Folgendes hinzufügen zusätzliche Abhängigkeiten zu Ihrer Gradle-Datei hinzufügen:

Cool

dependencies {
    implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'
}

Kotlin

dependencies {
    implementation("androidx.hilt:hilt-navigation-compose:1.0.0")
}

Wenn Sie „Navigation Compose“ verwenden, nutzen Sie immer die zusammensetzbare Funktion hiltViewModel , um eine Instanz der mit @HiltViewModel annotierten ViewModel abzurufen. Dies funktioniert mit Fragmenten oder Aktivitäten, die mit @AndroidEntryPoint

Beispiel: Wenn ExampleScreen ein Ziel in einer Navigationsgrafik ist, hiltViewModel() aufrufen, um eine Instanz des Bereichs ExampleViewModel abzurufen an das Ziel, wie im folgenden Code-Snippet gezeigt:

// 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)
        }
        /* ... */
    }
}

Wenn Sie die Instanz eines ViewModel abrufen müssen, der sich auf Navigationsrouten oder die Navigationsdiagramm verwenden Sie stattdessen die zusammensetzbare Funktion hiltViewModel und übergeben Sie die entsprechende backStackEntry als Parameter verwenden:

// 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

Die Paging Mediathek erleichtert das schrittweise Laden von Daten und diese Funktion wird in Compose unterstützt. Die Version „Paging“ Seite enthält Informationen über die zusätzliche paging-compose-Abhängigkeit, die hinzugefügt werden muss auf das Projekt und seine Version.

Hier ein Beispiel für die Compose APIs der Paging-Bibliothek:

@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")
        }
    }
}

Weitere Informationen finden Sie in der Dokumentation zu Listen und Rastern. zur Verwendung von Paging beim Schreiben.

Maps

Mit der Funktion Maps Compose um Google Maps in Ihrer App bereitzustellen. Hier ein Anwendungsbeispiel:

@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"
        )
    }
}