美文网首页
Jetpack Compose初识

Jetpack Compose初识

作者: 塞上牧羊空许约 | 来源:发表于2021-03-29 17:58 被阅读0次

    何为Compose

    2019 年中,Google 在 I/O 大会上公布的用于Android构建原生界面的全新 UI 框架。也就是说它的渲染机制、布局机制、触摸算法以及 UI 的具体写法,全都是新的。啊,这难道要把我们Android开发者赖以生存的技能---画xml,给点灭啦?

    为啥要学

    作为Google新推出的一套全新ui框架,Compose有别于传统的xml+java(kotlin)的“命令式ui”写法,它是一种“声明式ui”,iOS 的 SwiftUI 以及跨平台的 Flutter 也都是声明式的,可见声明式 UI 已经是一种趋势了(扶我起来,我还能学.jpg)。那它有那些好处呢?

    • 更少的代码
      用更少的代码来完成更多的功能,简单,易于维护,补充一下,Compose只能用Kotlin语言编写噢!
    • 直观
      只需要把ui元素描述出来即可,其他的交给Compose处理即可,一旦状态发生变化,你的ui也会自动更新
    • 加速开发
      兼容现有代码,Android Studio的实时预览便于快速迭代
    • 功能强大
      Android 平台 API 的直接访问和对于 Material Design、深色主题、动画等的内置支持

    Compose vs Xml+Java/Kotlin

    前者只要声明界面是什么样子,不用手动去更新,因为界面会自动更新,而且去掉了xml,只需使用Kotlin即可。而后者数据发生了改变,我们得手动用 Java 代码或者 Kotlin 代码去把新数据更新到界面。给出详细的步骤,去命令界面进行更新。

    xml

     setContentView(R.layout.activity_compare)
     findViewById<TextView>(R.id.tv_greeting).text = "Hello Android"
    

    compose

        @Preview
        @Composable
        fun FirstPreview() {
            var name by remember { mutableStateOf("Hello Compose") }
            Story(name)
            name = "Hello Android"
        }
    
        @Composable
        fun Story(name: String) {
            Text(name, textAlign = TextAlign.Center)
        }
    

    状态管理

    状态

    app中的状态(State)指的是一个可以随着时间变化的值。我们的应用就是在向用户展示状态。Compose可以让我们明确状态存储的位置和方式。

    组合和重组

    组合(composition)就是由一个个Composable调用形成的树形结构,运行这些Composable便可展示出我们的ui,在初识组合期间,Compose会对这些构建ui的Composable函数进行跟踪,当app的状态发生改变时,Compose会进行一次重组(recomposition)来更新ui。
    组合只能由初始组合产生,并且只能由重组更新。修改的唯一方法就是重组。
    Talk is cheap, show me the code

        // this stateful composable is only responsible for holding internal state
        // and defers the UI to the stateless composable
        @Composable
        fun ExpandingCard(title: String, body: String) {
            var expanded by remember { mutableStateOf(false) }
            ExpandingCard(
                title = title,
                body = body,
                expanded = expanded,
                onExpand = { expanded = true },
                onCollapse = { expanded = false }
            )
        }
        
        // this stateless composable is responsible for describing the UI based on the state
        // passed to it and firing events in response to the buttons being pressed
        @Composable
        fun ExpandingCard(
            title: String,
            body: String,
            expanded: Boolean,
            onExpand: () -> Unit,
            onCollapse: () -> Unit
        ) {
            Card {
                Column(
                    Modifier
                        .width(280.dp)
                        .animateContentSize() // automatically animate size when it changes
                        .padding(top = 16.dp, start = 16.dp, end = 16.dp)
                ) {
                    Text(title)
                    if (expanded) {
                        Spacer(Modifier.height(8.dp))
                        Text(body)
                        IconButton(onClick = onCollapse, Modifier.fillMaxWidth()) {
                            Icon(Icons.Default.KeyboardArrowUp, "Expand Less")
                        }
                    } else {
                        IconButton(onClick = onExpand, Modifier.fillMaxWidth()) {
                            Icon(Icons.Default.KeyboardArrowDown, contentDescription = "Expand more")
                        }
                    }
                }
            }
        }
    

    其中mutableState会返回一个MutableState,是一个可被观察的类型,它的值一旦发生变化,那么任何使用它的值的Composable函数将会发生重组,然后更新组合。remember的作用就是将状态的值存储在内存中,给Composable函数赋予”记忆“的功能,不会在每次重组中将上一次的值丢失。然而当发生切换屏幕方向,切换语言这些configuration changes时,remember便无能为力了,这时候rememberSaveable就可以派上用场啦。rememberSaveable可以自动将任何可以放在Bundle的值存储下来。

    Composable的生命周期

    lifecycle-composition.png

    互操作性

    Xml里使用Compose

    通过使用ComposeView然后调用setContent方法即可

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:orientation="vertical"
        tools:context=".compare.ComposeInXmlActivity">
        <TextView
            android:id="@+id/hello_world"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:text="Hello Android!" />
    
        <androidx.compose.ui.platform.ComposeView
            android:id="@+id/compose_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="center" />
    </LinearLayout>
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_compose_in_xml)
    
            findViewById<ComposeView>(R.id.compose_view).setContent {
                Text("Hello Compse")
            }
        }
    

    Compose里使用Android View

    通过使用AndoridView可以引入一个view

        @Composable
        private fun PlantDescription(description: String) {
            // Remembers the HTML formatted description. Re-executes on a new description
            val htmlDescription = remember(description) {
                HtmlCompat.fromHtml(description, HtmlCompat.FROM_HTML_MODE_COMPACT)
            }
    
            // Displays the TextView on the screen and updates with the HTML description when inflated
            // Updates to htmlDescription will make AndroidView recompose and update the text
            AndroidView(
                factory = { context ->
                    TextView(context).apply {
                        movementMethod = LinkMovementMethod.getInstance()
                    }
                },
                update = {
                    it.text = htmlDescription
                }
            )
        }
    
        @Preview
        @Composable
        private fun PlantDescriptionPreview() {
            MaterialTheme {
                PlantDescription("HTML<br><br>description")
            }
        }
    

    学习资源

    https://developer.android.com/jetpack/compose/state?hl=zh-cn

    相关文章

      网友评论

          本文标题:Jetpack Compose初识

          本文链接:https://www.haomeiwen.com/subject/twqrhltx.html