Jetpack Compose初识

何为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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,026评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,655评论 1 296
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,726评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,204评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,558评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,731评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,944评论 2 314
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,698评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,438评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,633评论 2 247
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,125评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,444评论 3 255
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,137评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,103评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,888评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,772评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,669评论 2 271

推荐阅读更多精彩内容