最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

Compose 中顯示數(shù)據(jù),要將其存儲(chǔ)在變量中,并用 mutableStateOf 包裹,以便自動(dòng)監(jiān)聽(tīng)

2023-04-01 21:14 作者:哆啦a夢(mèng)的道具師  | 我要投稿

在 Compose 中顯示數(shù)據(jù),通常我們要將其存儲(chǔ)在變量中,并用?mutableStateOf?包裹,以便實(shí)現(xiàn)自動(dòng)監(jiān)聽(tīng)與更新。這一步有下列三種寫法:

val name = mutableStateOf("Bob") ? ? ? ? ? ? ? // 1

val name by mutableStateOf("Bob") ? ? ? ? ? ? ?// 2

val name by remember { mutableStateOf("Bob") } // 3

Compose 過(guò)程

在深挖之前,有必要先了解 Compose 從構(gòu)建到顯示的完整過(guò)程。

Compose 分為三個(gè)步驟:組合 (compose)、布局、繪制。前者是 Compose 獨(dú)有的,后面兩個(gè)與傳統(tǒng) View 類似。所謂「組合」,就是根據(jù)我們寫的代碼創(chuàng)建出實(shí)際的界面,組合的結(jié)果稱為 Composition

插一句題外話,Compose 函數(shù)雖然看起來(lái)很像是創(chuàng)建一個(gè)對(duì)象,例如 Text(text = name.value) 很像創(chuàng)建一個(gè) Text 對(duì)象,但實(shí)際上不是這樣。跟蹤源碼可以發(fā)現(xiàn),這只不過(guò)是一個(gè)普通的函數(shù),它沒(méi)有返回值,因此類似 Text().text = name.value 的寫法完全錯(cuò)誤 ? 這與傳統(tǒng) View 中 TextView().text = "xxx" 不是一回事。

—— 所以需要「組合」


如果還是無(wú)法理解,可以將「組合」類比傳統(tǒng) View 中?inflat,解析 xml 文件創(chuàng)建實(shí)際的對(duì)象。只不過(guò)曾經(jīng)我們可以繞過(guò) xml 手動(dòng)創(chuàng)建 view,而現(xiàn)在不行了。

MutableState

最基本的用例大概是這樣:

val name = mutableStateOf("Bob")?

setContent { ? ?Column { ? ? ? ?Text(text = name.value) ? ? ??

Button(onClick = { name.value = "2" })?

{

? ? ? ? ? ?Text(text = "Change Name") ? ? ? ?

}

? ?}

}


定義了一個(gè) Text 和 Button,點(diǎn)擊按鈕,顯示的文本就會(huì)改變。

跟蹤源碼輕易看出,mutableStateOf() 就是創(chuàng)建一個(gè) ParcelableSnapshotMutableState 對(duì)象然后返回它。ParcelableSnapshotMutableState 本身并沒(méi)有什么有價(jià)值的東西,主要是對(duì) parcelable 的實(shí)現(xiàn)便于進(jìn)程通信。真正儲(chǔ)存數(shù)據(jù)的是它的父類 SnapshotMutableStateImpl

internal open class SnapshotMutableStateImpl<T>(

? ? value: T,

? ? override val policy: SnapshotMutationPolicy<T>

) : StateObject, SnapshotMutableState<T> {

? ? override var value: T

? ? ? ? get() = next.readable(this).value

? ? ? ? set(value) = next.withCurrent {

? ? ? ? ? ? if (!policy.equivalent(it.value, value)) {

? ? ? ? ? ? ? ? next.overwritable(this, it) { this.value = value }

? ? ? ? ? ? }

? ? ? ? }


? ? private var next: StateStateRecord<T> = StateStateRecord(value)


? ? override val firstStateRecord: StateRecord

? ? ? ? get() = next

? ? // 省略其他的 ...

}

顯然 value 就是保存實(shí)際數(shù)據(jù)的東西,可惜它依然不是最終實(shí)現(xiàn)。繼續(xù)探索便遇到一個(gè)關(guān)鍵類 StateRecordStateStateRecord 是它的子類),要搞清楚它,首先要看看 SnapshotMutableStateImpl 所實(shí)現(xiàn)的兩個(gè)接口?,F(xiàn)在我們已經(jīng)知道 mutableStateOf() 可以返回一個(gè)容器對(duì)象,它能夠被訂閱并且在內(nèi)部值改變時(shí)通知訂閱者,以此實(shí)現(xiàn) UI 自動(dòng)刷新?!副挥嗛啞惯@種特性其實(shí)是 StateObject 接口提供的,很反直覺(jué)。

再次套娃??,StateObject 本身又是一個(gè)容器,以鏈表的形式存儲(chǔ)著一串 StateRecord ?? 這個(gè)真正保存了數(shù)據(jù)。為什么是一串?因?yàn)樗粌H保存了變量的最新值,還保留了曾經(jīng)的值,以便實(shí)現(xiàn)「撤銷」等功能。既然是鏈表,那肯定存在第一個(gè)節(jié)點(diǎn),就是 StateObject.firstStateRecord ,后繼節(jié)點(diǎn)就是 StateRecord.next。注意這個(gè) next 和 SnapshotMutableStateImpl.next 無(wú)關(guān),恰好重名而已。事實(shí)上 SnapshotMutableStateImpl 里有一個(gè)鏈表保存著所有值(實(shí)現(xiàn)了 StateObject 接口呀),它的首個(gè)節(jié)點(diǎn)是 SnapshotMutableStateImpl.next。SnapshotMutableState

小結(jié):StateObject 以鏈表形式真正儲(chǔ)存了數(shù)據(jù),StateRecord 是鏈表的節(jié)點(diǎn),SnapshotMutableStateImpl 是一個(gè)實(shí)現(xiàn)。

作者:晨鶴
鏈接:https://juejin.cn/post/7057852733012836388
來(lái)源:稀土掘金
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處。


Compose 中顯示數(shù)據(jù),要將其存儲(chǔ)在變量中,并用 mutableStateOf 包裹,以便自動(dòng)監(jiān)聽(tīng)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
德昌县| 拉萨市| 淮安市| 贵州省| 固阳县| 伊川县| 堆龙德庆县| 英吉沙县| 甘肃省| 永新县| 池州市| 赤峰市| 汤阴县| 黄大仙区| 喜德县| 莎车县| 英山县| 凤山县| 平乐县| 紫金县| 岳阳市| 鹤壁市| 昭苏县| 江永县| 无棣县| 南郑县| 肥乡县| 雅安市| 普定县| 法库县| 新津县| 广南县| 阿勒泰市| 南召县| 天台县| 额尔古纳市| 沾化县| 高淳县| 黄龙县| 监利县| 蓬莱市|