Android Jetpack Compose résumé

Présentation

Jetpack Compose est une nouvelle façon de créer une interface utilisateur native. La méthode d'écriture est très similaire à Flutter. Les étudiants qui connaissent Flutter peuvent commencer rapidement.
Site officiel: https://developer.android.com/jetpack/compose
démo officielle: https://github.com/android/compose-samples
introduction officielle: https://developer.android.com/jetpack/compose/setup

Environnement et version

La prise en charge minimale est Android API 21, version 5.0, qui doit utiliser le langage kotlin, et la version minimale est Android Studio 4.0.
Jetpack Compose est actuellement au stade expérimental, il est maintenant de 0,1 dev2, et on estime qu'il faudra encore un an avant la version officielle de 1.0.
Les versions ultérieures peuvent ajouter plus de fonctionnalités kotlin, enrichir l'animation et d'autres problèmes de performances.

À propos de l'utilisation dans des projets existants:
https://developer.android.com/jetpack/compose/setup#add-compose

Comment utiliser

Composer un nouveau projet vide directement dans l'AS 4.0, il y a un exemple de code:
Insérez la description de l'image ici
ajouté avant que la fonction @Composeannotations, vous pouvez revenir à un Flutter similaire dans l'interface utilisateur Widget
ajouter des @Composefonctions d'annotation peuvent appeler l'autre, ces fonctions seront compilées plug-in de traitement Donc, si une fonction ne génère pas d'interface utilisateur, n'utilisez pas cette annotation.
@PreviewL'annotation peut être prévisualisée en temps réel sur la droite. Après avoir modifié la fonction, actualisez un aperçu. La fonction extérieure à laquelle l'annotation est ajoutée ne peut pas avoir de paramètres, mais une fonction avec des paramètres peut être imbriquée à l'intérieur pour être prévisualisée. Vous pouvez @Previewajouter un nom à l' arrière, tel que:@Preview("Text preview")

Les concepts de colonne et de ligne sont les mêmes que dans Flutter, y compris la taille du concept mainAxisSizeet l'alignement de l' axe principal et de l'axe secondaire crossAxisAlignment, et un exemple de code:

@Composable
fun MyScreenContent(
    names: List<String> = listOf("Android", "there"),
    counterState: CounterState = CounterState()
) {
    Column(crossAxisAlignment = CrossAxisAlignment.Center
      crossAxisSize = LayoutSize.Expand,
        mainAxisSize = LayoutSize.Expand) {
        for (name in names) {
            Greeting(name = name)
            Divider(color = Color.Black)
        }
        Divider(color = Color.Transparent, height = 32.dp)
        Counter(counterState)
    }
}

@Preview("MyScreen preview")
@Composable
fun DefaultPreview() {
    MyApp {
        MyScreenContent()
    }
}

Vous pouvez utiliser HeightSpacer(24.dp)ou WeightSpacer(24.dp)pour ajouter directement un intervalle de largeur et de hauteur

Selon les suggestions officielles, nous pouvons diviser l'interface utilisateur en plusieurs petites fonctions de composition. Chaque fonction sera éventuellement compilée par le plugin pour générer une vue, puis ces fonctions de composition pourront être réutilisées.

@Composable
fun MyScreenContent(
    names: List<String> = listOf("Android", "there"),
    counterState: CounterState = CounterState()
) {
    Column(modifier = ExpandedHeight, crossAxisAlignment = CrossAxisAlignment.Center) {
        Column(modifier = Flexible(1f), crossAxisAlignment = CrossAxisAlignment.Center) {
            for (name in names) {
                Greeting(name = name)
                Divider(color = Color.Black)
            }
        }
        Counter(counterState)
    }
}

Dans Colonne, vous pouvez définir ExpandedHeight sur le modificateur de paramètre, similaire à la signification de la définition de la hauteur match_parent, la largeur est la même.

À propos de l'utilisation du thème et de la personnalisation du thème

Il existe de nombreuses couleurs et styles de police dans MaterialTheme. Après avoir placé MaterialTheme dans le calque externe, vous pouvez utiliser les données de thème dans la fonction de composition interne, telles que:style = +themeTextStyle { h1 }

@Composable
fun Greeting(name: String) {
    Text (
        text = "Hello $name!",
        modifier = Spacing(24.dp),
        style = +themeTextStyle { h1 }
        color = +themeColor { surface }
    )
}

Vous pouvez modifier une certaine valeur d'attribut sur un thème existant en utilisant la fonction de copie, telle que:

textStyle = (+themeTextStyle { body1 }).copy(color = Color.Yellow)

Thème personnalisé

import androidx.compose.Composable

@Composable
fun CustomTheme(children: @Composable() () -> Unit) {
    // TODO 
}
import androidx.compose.Composable
import androidx.ui.core.CurrentTextStyleProvider
import androidx.ui.graphics.Color
import androidx.ui.material.MaterialColors
import androidx.ui.material.MaterialTheme
import androidx.ui.text.TextStyle

val green = Color(0xFF1EB980.toInt())
val grey = Color(0xFF26282F.toInt())
private val themeColors = MaterialColors(
    primary = green,
    surface = grey,
    onSurface = Color.White
)

@Composable
fun CustomTheme(children: @Composable() () -> Unit) {
    MaterialTheme(colors = themeColors) {
        val textStyle = TextStyle(color = Color.Red)
        CurrentTextStyleProvider(value = textStyle) {
            children()
        }
    }
}

Effets et mémo

Le rôle du mémo:

1. Lors des recompositions (c'est-à-dire lorsque les données du modèle à l'intérieur du composant d'interface utilisateur changent, le composant d'interface utilisateur sera reconstruit), enregistrez la valeur d'état, comme suit:

@Composable
fun MyScreenContent(
    names: List<String> = listOf("Android", "there"),
    counterState: CounterState = CounterState()
) { ... }

Il y a un problème avec le code ci-dessus. Lors de la reconstruction, la valeur counterState d'origine sera perdue, à chaque nouvel objet counterState.
Vous pouvez résoudre le problème après l'avoir modifié à l'aide du mémo comme suit:

@Composable
fun MyScreenContent(
    names: List<String> = listOf("Android", "there"),
    counterState: CounterState = +memo { CounterState() }
) { ... }

2. Lors de la réorganisation, n'oubliez pas certains résultats de calcul internes pour éviter plusieurs calculs

Si vous devez effectuer des calculs au milieu de la composition, mais que vous ne souhaitez pas effectuer de calculs chaque fois que vous recombinez la fonction, vous pouvez vous souvenir du calcul, même si la fonction Composable est recombinée, le calcul ne sera pas effectué à nouveau.

@Composable
fun Greeting(name: String) {

    val formattedName = +memo { name.substringBefore(" ").toUpperCase() }

    Text (
        text = "Hello $formattedName!",
        modifier = Spacing(24.dp),
        style = +themeTextStyle { h3 }
    )
}

@Preview
@Composable
fun DefaultPreview() {
    MaterialTheme {
        Greeting("Android 10")
    }
}

Par exemple, le processus de calcul formatedName ici ne sera pas répété après avoir utilisé le mémo, mais il y a un bogue écrit de cette façon. Si un autre paramètre est passé dans le deuxième appel, alors parce que le mémo réutilise le résultat d'origine, il Provoque un bug, donc pour les paramètres qui doivent être modifiés, memo peut être utilisé de la manière suivante:

@Composable
fun Greeting(name: String) {

    val formattedName = +memo(name) { name.substringBefore(" ").toUpperCase() }

    Text (
        text = "Hello $formattedName!",
        modifier = Spacing(24.dp),
        style = +themeTextStyle { h3 }
    )
}

@Model annoté

Une fois que l'annotation de modèle marque une classe de données, vous pouvez surveiller directement les modifications de données dans la fonction Composer et mettre à jour automatiquement l'affichage,
par exemple:
définition:

@Model 
class CounterState(var count: Int = 0)

Utilisation:

@Composable 
fun Counter(state: CounterState) {
    Button(
        text = "I've been clicked ${state.count} times",
        onClick = {
            state.count++
        }
    )
}

Promotion du statut, flux de données vers le bas, flux d'événements vers le haut

@Model
class FormState(var optionChecked: Boolean)

@Composable
fun Form(formState: FormState) {
    Checkbox(
        checked = formState.optionChecked,
        onCheckedChange = { newState -> formState.optionChecked = newState })
}

在上面代码中,Checkbox的选中状态,在Checkbox和Form中都不保存,而改为由外部传入,原因是此时外部可能需要使用当前的状态值,那么由外部来创建并传递该参数到Compose函数中,这使得外部调用者提升了状态

⚠️ Remarque: dans les fonctions composables, l'état qui peut être utile pour appeler la fonction doit être divulgué, car c'est la seule méthode qui peut être utilisée ou contrôlée, appelée promotion d'état.

Le concept de promotion de l'état est le même que celui de Flutter. À l'avenir, il devrait également introduire des bibliothèques de gestion d'état connexes telles que Provider, BLOC ou Redux dans Flutter, car la manière d'annoter Compose + Model est une idée MVVM et a besoin de commodité. Une bibliothèque tripartite de gestion de l'état des données le fait.

Concernant le flux de données: la fonction Composable parent peut contrôler ses données enfants. L'interface de sous-composition ne doit pas être lue à partir de variables globales ou d'un stockage de données global. Les fonctions composables ne doivent recevoir que les informations requises, elles doivent donc être aussi simples que possible, plutôt que d'appeler tout ce que la fonction composable parent peut fournir.

@Composable
fun MultipleGreetings(user: User = +memo { User("name", "surname") }) {
    Column {
        Greeting("${user.firstName} ${user.lastName}")
        Greeting("Android 10")
        Button(text = "Change name", onClick = {
            user.firstName = "Changed"
            user.lastName = "New surname"
        })
    }
}

@Composable
fun Greeting(name: String) {

    val formattedName = +memo(name) { name.substringBefore(" ").toUpperCase() }

    Text (
        text = "Hello $formattedName!",
        modifier = Spacing(24.dp),
        style = +themeTextStyle { h3 }
    )
}

比如上面代码中,Greeting从调用方Compose函数(MultipleGreetings)获取数据,作为参数传入,且Greeting只接收一个String,并不是整个User对象。

Événement passant

L'événement continue de monter à travers le rappel lambda. Lorsque la fonction Composable enfant reçoit un événement, la modification doit être propagée à nouveau au Composable qui se soucie des informations.

Dans notre exemple, nous pouvons rendre Greeting cliquable en encapsulant le contenu de Greeting dans une fonction Clickable (disponible dans la bibliothèque) qui prend un écouteur onClick comme paramètre. Cependant, Greeting est une fonction réutilisable, il ne sait pas comment gérer l'interaction utilisateur. Vous devez utiliser lambda pour propager ces informations du bas de la hiérarchie (composable cliquable dans le message d'accueil) aux fonctions composables en haut, qui savent comment gérer ces informations, comme le montre l'exemple suivant:

@Composable
fun MultipleGreetings(user: User = +memo { User("name", "surname") }) {

    val onClick = {
        user.firstName = "Changed"
    }

    Column {
        Greeting("${user.firstName} ${user.lastName}", onClick)
        Greeting("Android 10", onClick)
        Button(text = "Change name", onClick = onClick)
    }
}

@Composable
fun Greeting(name: String, onClick: () -> Unit) {

    val formattedName = +memo(name) { name.substringBefore(" ").toUpperCase() }

    Clickable(onClick = onClick) {
        Text (
            text = "Hello $formattedName!",
            modifier = Spacing(24.dp),
            style = +themeTextStyle { h3 }
        )
    }
}

Greeting indique à MultipleGreetings qu'il a été cliqué en appelant le lambda passé par le parent en tant que paramètre. Si vous exécutez l'application, vous pouvez voir que le fait de cliquer sur n'importe quel texte de message d'accueil propage les modifications et que l'instance de message d'accueil en haut est regroupée.

Insérez la description de l'image ici
Flux de données dans les applications Compose.  Les données descendent avec les paramètres, les événements remontent avec les lambdas.
Flux de données dans les applications Compose. Les données descendent avec les paramètres, les événements remontent avec les lambdas.


Composer et afficher l'interopérabilité existante

Les fonctions écrites par Compose peuvent être utilisées en XML, et la vue existante d'Android peut également être écrite en Compose, comme:
Insérez la description de l'image ici
Insérez la description de l'image ici
Résumé: Compose s'appuie sur la méthode d'écriture de Flutter et Swift UI, le code est concis, vous pouvez prévisualiser l'effet en temps réel, à partir de 2019 Le 19 novembre, la version actuelle n'était que de 0,1. Il est prévu qu'après la sortie officielle de la version 1.0, il y aura plus de mises à jour de fonctions. Une petite démo quotidienne peut être d'abord familiarisée avec Compose.

Référence:
https://codelabs.developers.google.com/codelabs/jetpack-compose-basics/#0

Excellent! Le dernier développement de la bibliothèque de composants de l'interface utilisateur Android Jetpack Compose, écrit exactement comme Flutter

Dernières avancées d'Android Studio 4.0, ces nouvelles fonctionnalités sont incroyables!

A publié 82 articles originaux · J'aime 86 · Plus de 110 000 visiteurs

Je suppose que tu aimes

Origine blog.csdn.net/unicorn97/article/details/103137105
conseillé
Classement