Jetpack Compose初識(shí)

何為Compose

2019 年中乏德,Google 在 I/O 大會(huì)上公布的用于Android構(gòu)建原生界面的全新 UI 框架洪唐。也就是說(shuō)它的渲染機(jī)制谐鼎、布局機(jī)制唯咬、觸摸算法以及 UI 的具體寫(xiě)法席楚,全都是新的咬崔。啊,這難道要把我們Android開(kāi)發(fā)者賴以生存的技能---畫(huà)xml烦秩,給點(diǎn)滅啦垮斯?

為啥要學(xué)

作為Google新推出的一套全新ui框架,Compose有別于傳統(tǒng)的xml+java(kotlin)的“命令式ui”寫(xiě)法只祠,它是一種“聲明式ui”甚脉,iOS 的 SwiftUI 以及跨平臺(tái)的 Flutter 也都是聲明式的,可見(jiàn)聲明式 UI 已經(jīng)是一種趨勢(shì)了(扶我起來(lái)铆农,我還能學(xué).jpg)牺氨。那它有那些好處呢?

  • 更少的代碼
    用更少的代碼來(lái)完成更多的功能墩剖,簡(jiǎn)單猴凹,易于維護(hù),補(bǔ)充一下岭皂,Compose只能用Kotlin語(yǔ)言編寫(xiě)噢郊霎!
  • 直觀
    只需要把ui元素描述出來(lái)即可,其他的交給Compose處理即可爷绘,一旦狀態(tài)發(fā)生變化书劝,你的ui也會(huì)自動(dòng)更新
  • 加速開(kāi)發(fā)
    兼容現(xiàn)有代碼,Android Studio的實(shí)時(shí)預(yù)覽便于快速迭代
  • 功能強(qiáng)大
    Android 平臺(tái) API 的直接訪問(wèn)和對(duì)于 Material Design土至、深色主題购对、動(dòng)畫(huà)等的內(nèi)置支持

Compose vs Xml+Java/Kotlin

前者只要聲明界面是什么樣子,不用手動(dòng)去更新陶因,因?yàn)榻缑鏁?huì)自動(dòng)更新骡苞,而且去掉了xml,只需使用Kotlin即可。而后者數(shù)據(jù)發(fā)生了改變解幽,我們得手動(dòng)用 Java 代碼或者 Kotlin 代碼去把新數(shù)據(jù)更新到界面贴见。給出詳細(xì)的步驟,去命令界面進(jìn)行更新躲株。

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

狀態(tài)管理

狀態(tài)

app中的狀態(tài)(State)指的是一個(gè)可以隨著時(shí)間變化的值片部。我們的應(yīng)用就是在向用戶展示狀態(tài)。Compose可以讓我們明確狀態(tài)存儲(chǔ)的位置和方式霜定。

組合和重組

組合(composition)就是由一個(gè)個(gè)Composable調(diào)用形成的樹(shù)形結(jié)構(gòu)吞琐,運(yùn)行這些Composable便可展示出我們的ui,在初識(shí)組合期間,Compose會(huì)對(duì)這些構(gòu)建ui的Composable函數(shù)進(jìn)行跟蹤然爆,當(dāng)app的狀態(tài)發(fā)生改變時(shí),Compose會(huì)進(jìn)行一次重組(recomposition)來(lái)更新ui黍图。
組合只能由初始組合產(chǎn)生曾雕,并且只能由重組更新。修改的唯一方法就是重組助被。
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會(huì)返回一個(gè)MutableState,是一個(gè)可被觀察的類型剖张,它的值一旦發(fā)生變化,那么任何使用它的值的Composable函數(shù)將會(huì)發(fā)生重組揩环,然后更新組合搔弄。remember的作用就是將狀態(tài)的值存儲(chǔ)在內(nèi)存中,給Composable函數(shù)賦予”記憶“的功能丰滑,不會(huì)在每次重組中將上一次的值丟失顾犹。然而當(dāng)發(fā)生切換屏幕方向,切換語(yǔ)言這些configuration changes時(shí)褒墨,remember便無(wú)能為力了炫刷,這時(shí)候rememberSaveable就可以派上用場(chǎng)啦。rememberSaveable可以自動(dòng)將任何可以放在Bundle的值存儲(chǔ)下來(lái)郁妈。

Composable的生命周期

lifecycle-composition.png

互操作性

Xml里使用Compose

通過(guò)使用ComposeView然后調(diào)用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

通過(guò)使用AndoridView可以引入一個(gè)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")
        }
    }

學(xué)習(xí)資源

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末浑玛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子噩咪,更是在濱河造成了極大的恐慌顾彰,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件胃碾,死亡現(xiàn)場(chǎng)離奇詭異涨享,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)仆百,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)灰伟,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事栏账√澹” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵挡爵,是天一觀的道長(zhǎng)竖般。 經(jīng)常有香客問(wèn)我,道長(zhǎng)茶鹃,這世上最難降的妖魔是什么涣雕? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮闭翩,結(jié)果婚禮上挣郭,老公的妹妹穿的比我還像新娘。我一直安慰自己疗韵,他們只是感情好兑障,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著蕉汪,像睡著了一般流译。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上者疤,一...
    開(kāi)封第一講書(shū)人閱讀 52,328評(píng)論 1 310
  • 那天福澡,我揣著相機(jī)與錄音,去河邊找鬼驹马。 笑死革砸,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的糯累。 我是一名探鬼主播业岁,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼寇蚊!你這毒婦竟也來(lái)了笔时?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤仗岸,失蹤者是張志新(化名)和其女友劉穎允耿,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體扒怖,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡较锡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了盗痒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蚂蕴。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡低散,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出骡楼,到底是詐尸還是另有隱情熔号,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布鸟整,位于F島的核電站引镊,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏篮条。R本人自食惡果不足惜弟头,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望涉茧。 院中可真熱鬧赴恨,春花似錦、人聲如沸伴栓。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)挣饥。三九已至,卻和暖如春沛膳,著一層夾襖步出監(jiān)牢的瞬間扔枫,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工锹安, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留短荐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓叹哭,卻偏偏與公主長(zhǎng)得像忍宋,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子风罩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容