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閱讀 227,748評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,165評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,595評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,633評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,435評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,943評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,035評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,175評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,713評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,599評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,788評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,303評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,034評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,412評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,664評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,408評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,747評論 2 370

推薦閱讀更多精彩內容