La próxima frontera tecnológica de Android: dominar Jetpack Compose rápidamente

Introducción a Componer

  • Jetpack Compose: un kit de herramientas para crear una interfaz nativa (UI) de Android mediante programación declarativa

Ventaja

  • Menos código, menos código
  • Fuerte soporte de herramienta/componente
  • API intuitiva de Kotlin
  • Fácil de usar

Componer ideas de programación

  • Paradigma de programación declarativa: las funciones declarativas crean un componente de interfaz simple sin modificar ningún diseño XML ni usar un editor de diseño, simplemente llame a la función Jetpack Compose para declarar el elemento deseado, y el compilador Compose hará el resto del trabajo

  • Por ejemplo: funciones componibles simples

    class MainActivity : ComponentActivity() {
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContent {
                Text("Hello world!")
            }
        }
    }
    

  • Dinámico: la función de composición está escrita en Kotlin en lugar de XML, consulte $namela entrada anterior

  • Cosas a las que prestar atención:

    • Las funciones componibles se pueden ejecutar en cualquier orden

      //可以按任何顺序进行,不能让 StartScreen() 设置某个全局变量(附带效应)并让 MiddleScreen() 利用这项更改。相反,其中每个函数都需要保持独立。
      @Composable
      fun ButtonRow() {
          MyFancyNavigation {
              StartScreen()
              MiddleScreen()
              EndScreen()
          }
      }
      
    • Las funciones componibles se pueden ejecutar en paralelo

      • Compose puede optimizar la reorganización ejecutando funciones componibles en paralelo, de modo que Compose pueda aprovechar múltiples núcleos y ejecutar funciones componibles con menor prioridad (fuera de la pantalla)

      • Esta optimización significa que las funciones componibles pueden ejecutarse en un grupo de subprocesos en segundo plano, y si una función componible llama a una función en un ViewModel, Compose puede llamar a esa función desde varios subprocesos al mismo tiempo.

      • Cuando se llama a una función componible, la llamada puede ocurrir en un subproceso diferente al de la persona que llama, lo que significa que se debe evitar el código que modifica las variables en un lambda componible, tanto porque dicho código no es seguro para subprocesos como porque es un efecto secundario. no permitido por lambdas componibles

      //此代码没有附带效应
      @Composable
      fun ListComposable(myList: List<String>) {
          Row(horizontalArrangement = Arrangement.SpaceBetween) {
              Column {
                  for (item in myList) {
                      Text("Item: $item")
                  }
              }
              Text("Count: ${myList.size}")
          }
      }
      
      
      //如果函数写入局部变量,则这并非线程安全或正确的代码:
      @Composable
      @Deprecated("Example with bug 有问题的代码")
      fun ListWithBug(myList: List<String>) {
          var items = 0
      
          Row(horizontalArrangement = Arrangement.SpaceBetween) {
              Column {
                  for (item in myList) {
                      Text("Item: $item")
                      items++ // Avoid! Side-effect of the column recomposing.
                  }
              }
              Text("Count: $items")
          }
      }
      //每次重组时,都会修改 items。这可以是动画的每一帧,或是在列表更新时。但不管怎样,界面都会显示错误的项数。因此,Compose 不支持这样的写入操作;通过禁止此类写入操作,我们允许框架更改线程以执行可组合 lambda。
      复制代码
      
    • La reestructuración omite tantas funciones componibles y lambdas como sea posible

    • La reorganización es una operación optimista y puede cancelarse

    • Una función componible puede ejecutarse con la misma frecuencia que cada fotograma de la animación.

Preparación ambiental

  • Los estudiantes que ya saben, pueden saltar directamente

  • Necesita actualizar a la versión Arctic Fox 2020-3-1 o superior, el estudio de Android debajo de esta versión no tiene este soporte- [Descargue el último estudio de Android]

  • Nos dimos cuenta de que este proyecto solo es compatible con Kotlin mínimo sdk versión 21, Android 5.0

  • Dependencias relacionadas con Gradle Compose
implementation "androidx.compose.ui:ui:$compose_version"
    implementation "androidx.compose.material:material:$compose_version"
    implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
    implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.3.1'
    implementation 'androidx.activity:activity-compose:1.3.0-alpha06'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.3'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
    androidTestImplementation "androidx.compose.ui:ui-test-junit4:$compose_version"
    debugImplementation "androidx.compose.ui:ui-tooling:$compose_version"
 kotlinOptions {
        jvmTarget = '1.8'
        useIR = true//在 Gradle 构建脚本中指定额外编译器选项即可启用新的 JVM IR 后端
    }
composeOptions {
        kotlinCompilerExtensionVersion compose_version
        kotlinCompilerVersion '1.5.10'
    }
buildFeatures {
        compose true
    }
packagingOptions {
        resources {
            excludes += '/META-INF/{AL2.0,LGPL2.1}'
        }
    }
  • Dado que la nueva versión invita a Java 11, se requieren las siguientes correcciones para instalar el entorno Java 8
Android Gradle plugin requires Java 11 to run. You are currently using Java 1.8.
     You can try some of the following options:
       - changing the IDE settings.
       - changing the JAVA_HOME environment variable.
       - changing `org.gradle.java.home` in `gradle.properties`.      
org.gradle.java.home=/Library/Java/JavaVirtualMachines/jdk-11.0.11.jdk/Contents/Home

  • @Preview funciona, el entorno está bien

diseño

  • En la relación de cambio de estado xml tradicional de Android, los programadores necesitan una gran cantidad de código para mantener la interfaz de la interfaz de usuario para lograr la corrección del estado de la interfaz, lo que lleva mucho tiempo y trabajo. Incluso con la ayuda de la arquitectura MVVM, es Todavía es necesario mantener el estado, porque solo hay un conjunto de diseños.

  • La diferencia entre la implementación XML declarativa y tradicional, el diseño declarativo de Compose reconstruye directamente la interfaz de usuario, por lo que no habrá problemas de estado

  • Texto : Compose proporciona las funciones básicas BasicTexty BasicTextField, que son las funciones principales para mostrar texto y procesar la entrada del usuario. Compose también ofrece funciones más avanzadas TextyTextField

    Text("Hello World")
    
  • Reorganizar Texto->Botón

    @Composable
    fun ClickCounter(clicks: Int, onClick: () -> Unit) {
        Button(onClick = onClick) {
            Text("I've been clicked $clicks times")
        }
    }
    
  • El modificador puede modificar la posición, la altura, el margen, la alineación, etc. de los controles

    //`padding` 设置各个UI的padding。padding的重载的方法一共有四个。
    Modifier.padding(10.dp) // 给上下左右设置成同一个值
    Modifier.padding(10.dp, 11.dp, 12.dp, 13.dp) // 分别为上下左右设值
    Modifier.padding(10.dp, 11.dp) // 分别为上下和左右设值
    Modifier.padding(InnerPadding(10.dp, 11.dp, 12.dp, 13.dp))// 分别为上下左右设值
    //这里设置的值必须为`Dp`,`Compose`为我们在Int中扩展了一个方法`dp`,帮我们转换成`Dp`。
    //`plus` 可以把其他的Modifier加入到当前的Modifier中。
    Modifier.plus(otherModifier) // 把otherModifier的信息加入到现有的modifier中
    //`fillMaxHeight`,`fillMaxWidth`,`fillMaxSize` 类似于`match_parent`,填充整个父layout。
    Modifier.fillMaxHeight() // 填充整个高度
    //`width`,`heigh`,`size` 设置Content的宽度和高度。
    Modifier.width(2.dp) // 设置宽度
    Modifier.height(3.dp)  // 设置高度
    Modifier.size(4.dp, 5.dp) // 设置高度和宽度
    //`widthIn`, `heightIn`, `sizeIn` 设置Content的宽度和高度的最大值和最小值。
    Modifier.widthIn(2.dp) // 设置最大宽度
    Modifier.heightIn(3.dp) // 设置最大高度
    Modifier.sizeIn(4.dp, 5.dp, 6.dp, 7.dp) // 设置最大最小的宽度和高度
    //`gravity` 在`Column`中元素的位置。
    Modifier.gravity(Alignment.CenterHorizontally) // 横向居中
    Modifier.gravity(Alignment.Start) // 横向居左
    Modifier.gravity(Alignment.End) // 横向居右
    //`rtl`, `ltr` 开始布局UI的方向。
    Modifier.rtl  // 从右到左
    //更多Modifier学习:https://developer.android.com/jetpack/compose/modifiers-list
    
  • ColumnDisposición lineal ≈Android LinearLayout-VERTICAL

  • RowDisposición horizontal ≈Android LinearLayout-HORIZONTAL

  • BoxDiseño de marco ≈ Android FrameLayout, puede colocar un elemento encima de otro, Rowpara establecer la posición de los niños en , establecer los parámetroshorizontalArrangement y . verticalAlignmentPara Column, establezca verticalArrangementlos horizontalAlignmentparámetros y

  • Disposición relativa, necesidad de introducirConstraintLayout

    • introducir
    implementation "androidx.constraintlayout:constraintlayout-compose:1.0.0-beta02"
    
    • constraintlayout-composeproceso de uso

    • Ejemplo de uso completo

    @Composable
    fun testConstraintLayout() {
        ConstraintLayout() {
            //通过createRefs创建三个引用
            val (imageRef, nameRef) = createRefs()
            Image(painter = painterResource(id = R.mipmap.test),
                contentDescription = "图",
                modifier = Modifier
                    .constrainAs(imageRef) {//通过constrainAs将Image与imageRef绑定,并增加约束
                        top.linkTo(parent.top)
                        start.linkTo(parent.start)
                        bottom.linkTo(parent.bottom)
                    }
                    .size(100.dp)
                    .clip(shape = RoundedCornerShape(5)),
                contentScale = ContentScale.Crop)
            Text(
                text = "名称",
                modifier = Modifier
                    .constrainAs(nameRef) {
                        top.linkTo(imageRef.top, 2.dp)
                        start.linkTo(imageRef.end, 12.dp)
                        end.linkTo(parent.end)
                        width = Dimension.fillToConstraints
                    }
                    .fillMaxWidth(),
                fontSize = 18.sp,
                maxLines = 1,
                textAlign = TextAlign.Left,
                overflow = TextOverflow.Ellipsis,
            )
        }
    }
    

lista

  • diseño desplazable
//我们可以使用 verticalScroll() 修饰符使 Column 可滚动
Column (
        modifier = Modifier.verticalScroll(rememberScrollState())){
        messages.forEach { message ->
            MessageRow(message)
        }
    }
  • Sin embargo, el diseño anterior no se puede reutilizar, lo que puede ocasionar problemas de rendimiento. A continuación, se presentan nuestros diseños clave, lista

  • LazyColumn/LazyRow==RecylerView/listViewEl diseño de la lista, que resuelve el problema de rendimiento al desplazarse, yLazyColumn la diferencia entre el diseño de los elementos de la lista y la dirección de desplazamiento son diferentesLazyRow

    • relleno

      LazyColumn(
          contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp),
      ) {
          // ...
      }
      
    • espacio entre elementos

      LazyColumn(
          verticalArrangement = Arrangement.spacedBy(4.dp),
      ) {
          // ...
      }
      
    • Encabezados flotantes para listas flotantes, se pueden usar LazyColumnpara implementar encabezados fijos, se pueden usar stickyHeader()funciones experimentales

      @OptIn(ExperimentalFoundationApi::class)
      @Composable
      fun ListWithHeader(items: List<Item>) {
          LazyColumn {
              stickyHeader {
                  Header()
              }
      
              items(items) { item ->
                  ItemRow(item)
              }
          }
      }
      
  • diseño de cuadrículaLazyVerticalGrid

    @OptIn(ExperimentalFoundationApi::class)
    @Composable
    fun PhotoGrid(photos: List<Photo>) {
        LazyVerticalGrid(
            cells = GridCells.Adaptive(minSize = 128.dp)
        ) {
            items(photos) { photo ->
                PhotoItem(photo)
            }
        }
    }
    

diseño personalizado

  • Logrado al reorganizar el diseño básico

  • Lienzo

    Canvas(modifier = Modifier.fillMaxSize()) {
        val canvasWidth = size.width
        val canvasHeight = size.height
        drawCircle(
            color = Color.Blue,
            center = Offset(x = canvasWidth / 2, y = canvasHeight / 2),
            radius = size.minDimension / 4
        )
    }
    //drawCircle 画圆
    //drawRectangle 画矩形
    //drawLine //画线
    

animación

  • Selección de API de animación

Otro soporte de biblioteca

Resumir

  • En general, Compose es más simple y eficiente para la implementación de diseños nativos de Android, lo cual vale la pena aprender.
  • La escritura compuesta es muy similar a Flutter-Dart. Más adelante podemos hacer algunas comparaciones con el diseño de escritura de voz de Flutter-Dart.

Supongo que te gusta

Origin blog.csdn.net/ajsliu1233/article/details/120655616
Recomendado
Clasificación