Compose發(fā)布正式版已經(jīng)有一段時(shí)間了。趁最近比較閑,抓緊學(xué)習(xí)一波。
學(xué)習(xí)過(guò)程中,主要以實(shí)戰(zhàn)項(xiàng)目中常用技術(shù)為目標(biāo)。下面是項(xiàng)目地址,會(huì)長(zhǎng)期更新,希望能給正在學(xué)習(xí)Compose的小伙伴一點(diǎn)參考。同時(shí)您有什么好的建議,也可以提issue給我,我們一起討論。
項(xiàng)目地址:https://github.com/guozhiqiang123/compose-study
目標(biāo)
- 配合Retrofit+Okhttp實(shí)現(xiàn)數(shù)據(jù)加載并展示
- 實(shí)現(xiàn)列表的上拉加載更多、下來(lái)刷新
- 項(xiàng)目采用單頁(yè)面
- 使用compose-navigation實(shí)現(xiàn)路由導(dǎo)航
- 使用ViewModel+LiveData實(shí)現(xiàn)MVVM架構(gòu)
- 使用ViewModel+Flow(LiveData)實(shí)現(xiàn)MVI架構(gòu)
- 導(dǎo)航動(dòng)畫(huà)使用
- compose中嵌入原生控件
- 常見(jiàn)的動(dòng)畫(huà)使用
- 全局狀態(tài)的管理
- 適配平板
- 暗黑適配
- 多主題定制,切換
- 自定義組件
- 視頻列表實(shí)現(xiàn)和優(yōu)化
- 嵌入網(wǎng)頁(yè),和js交互
- compose-permission使用
- compose-pager使用
- 流式布局實(shí)現(xiàn)和優(yōu)化
- Material3主題適配
- 實(shí)現(xiàn)至少兩個(gè)復(fù)雜頁(yè)面并交互
- 登錄功能,并實(shí)現(xiàn)全局登錄狀態(tài)的同步
- 本地?cái)?shù)據(jù)存儲(chǔ)Room、DataStore等組件的使用
- 自定義頁(yè)面狀態(tài)管理組件
- 代碼質(zhì)量檢測(cè)工具
- 老項(xiàng)目混寫(xiě)Compose
- 其他更高級(jí)的功能,想到再補(bǔ)充
知識(shí)點(diǎn)
這只是我自己學(xué)習(xí)過(guò)程中的筆記和思考,可能不是完全正確,如有錯(cuò)誤,忘指正!
SnackBar的使用
//第一步:
val snackbarHostState = remember { SnackbarHostState() }
//通過(guò)kotlin Channel發(fā)送消息
val channel = remember { Channel<String>(Channel.CONFLATED) }
//第二步:
LaunchedEffect(key1 = channel) {
channel.receiveAsFlow().collect {
snackbarHostState.showSnackbar(it)
}
}
//第三步:
Scaffold(
modifier = Modifier.fillMaxSize(),
backgroundColor = Color.Transparent,
scaffoldState = rememberScaffoldState(snackbarHostState = snackbarHostState)
) {
}
//第四步:
channel.trySend("需要顯示的文本")
和ViewModel配合使用
使用ViewModel擴(kuò)展函數(shù)需要添加下面組件:
implementation "androidx.lifecycle:lifecycle-viewmodel-compose:2.5.1"
//示例代碼
@Composable
fun HomeMainPage(viewModel: HomeMainViewModel = viewModel()) {}
將LiveData轉(zhuǎn)換成State需要添加下面組件:
implementation "androidx.compose.runtime:runtime-livedata:1.2.1"
//示例代碼
val counter = viewModel.counter.observeAsState()
軟鍵盤(pán)顯示/隱藏的控制
val keyboard = LocalSoftwareKeyboardController.current
// ...
onClick = {
keyboard?.hide()
keyboard?.show()
}
不借助State手動(dòng)刷新(不推薦這么做)
//觸發(fā)當(dāng)前Composable的recomposition
currentRecomposeScope.invalidate()
Effect的使用
教程:https://juejin.cn/post/6930785944580653070
流程:

DisposableEffect
和生命周期相關(guān)的邏輯執(zhí)行使用。比如廣播注冊(cè)和反注冊(cè)、監(jiān)聽(tīng)和注銷(xiāo)監(jiān)聽(tīng)等等。
key1傳Unit或者true,首次渲染執(zhí)行一次,重組則不再執(zhí)行。key1傳State,則State值變化,則再次執(zhí)行。
SideEffect
每次重組都需要執(zhí)行的副作用。比如日志打印等等。
LaunchedEffect
需要調(diào)用協(xié)程函數(shù)的時(shí)候使用。
key1傳Unit或者true,首次渲染執(zhí)行一次,重組則不再執(zhí)行。key1傳State,如果State值變化,則再次執(zhí)行。
如果是條件啟動(dòng)該副作用,條件應(yīng)該寫(xiě)在外面,而不是LaunchedEffect里面,盡量減少資源的浪費(fèi)。
Compose函數(shù)中dp轉(zhuǎn)px
import androidx.compose.ui.platform.LocalDensity
val pxValue = with(LocalDensity.current) { 16.dp.toPx() }
// or
val pxValue = LocalDensity.current.run { 16.dp.toPx() }
設(shè)置部分文字不可復(fù)制
// 設(shè)置可選區(qū)域
SelectionContainer {
// Column等價(jià)于豎直的LinearLayout
Column {
Text(text = "可以選中我,可以選中我,可以選中我")
// 設(shè)置不可選區(qū)域
DisableSelection {
Text(text = "選不中我,選不中我,選不中")
}
// 位于可選區(qū)域內(nèi),可選
Text(text = "可以選中我,可以選中我,可以選中我")
}
}
物理返回鍵的處理
使用BackHandler進(jìn)行攔截,但是不能寫(xiě)在MaterialTheme的代碼塊中,否則不生效
@Composable
fun TestPage(){
BackHandler {
//TODO:攔截物理返回鍵
}
MaterialTheme {
androidx.compose.material.Scaffold {
Box(Modifier.padding(it)) {
}
}
}
}
我的一點(diǎn)看法
我之前用Flutter寫(xiě)過(guò)幾個(gè)demo,逐漸熟悉了寫(xiě)Flutter后,感覺(jué)寫(xiě)起來(lái)真好。特別是Android Studio各種智能補(bǔ)全,寫(xiě)起來(lái)特別流暢。所以一直比較抵觸學(xué)Compose,總感覺(jué)比Flutter書(shū)寫(xiě)體驗(yàn)差太多了。不過(guò)我畢竟還是一個(gè)Android開(kāi)發(fā)嘛,還指望著吃這碗飯,所以Android這邊的新技術(shù)也要學(xué)習(xí)起來(lái)。
寫(xiě)這篇文章的時(shí)候,我前前后后學(xué)Compose大概花了一周。主要是remember和Effect都是新概念,從接觸到理解個(gè)大概,花了一些時(shí)間。如果有學(xué)習(xí)過(guò)React前端技術(shù)的,應(yīng)該立馬就能明白,可惜我并沒(méi)有這樣的經(jīng)驗(yàn)。
學(xué)習(xí)了基本的組件后,我就開(kāi)始寫(xiě)上面這個(gè)項(xiàng)目,剛開(kāi)始寫(xiě)起來(lái)有點(diǎn)生疏。比如狀態(tài)提升什么的,剛開(kāi)始寫(xiě)完全沒(méi)注意到。不過(guò)隨著業(yè)務(wù)逐漸偏向于實(shí)戰(zhàn)項(xiàng)目,不斷重構(gòu)和優(yōu)化代碼,狀態(tài)提升這個(gè)東西,自然而然就有了。
代碼寫(xiě)的好不好,性能怎么樣。除了直覺(jué)感受,更重要的是要有工具來(lái)檢測(cè),于是又到處搜文章看,然后嘗試大佬們推薦的做法。工具有了之后,又把之前性能不好的地方重構(gòu)了下。
總體來(lái)說(shuō),目前Compose已經(jīng)很好了,我個(gè)人感覺(jué)性能上不比原生差。而且函數(shù)組合方式真的比類(lèi)繼承好使多了,非常靈活,而且少很多模板代碼。寫(xiě)動(dòng)畫(huà)真的不要太爽,原生項(xiàng)目寫(xiě)個(gè)動(dòng)畫(huà)有多痛苦,相信做過(guò)原生開(kāi)發(fā)的小伙伴都知道。另外自定義控件比原生容易多了,原生自定義需要理解很多概念,什么ViewGroup,View,事件傳遞等等。而Compose相對(duì)來(lái)說(shuō)理解的概念就少多了,而且代碼更簡(jiǎn)潔。有時(shí)候寥寥幾句代碼,就能實(shí)現(xiàn)很復(fù)雜的組件。
希望想在Android領(lǐng)域繼續(xù)討飯吃的小伙伴都學(xué)起來(lái)吧!
感謝你們(排名不分先后)
- Android官方教程
- 程序員江同學(xué)
- funroid
- FunnySaltyFish
- 其他大佬的博文(遇到問(wèn)題搜索到的,記不住了,望理解)
持續(xù)更新中...
除了項(xiàng)目持續(xù)更新,該文章也會(huì)持續(xù)更新。大家一起學(xué)習(xí),共同進(jìn)步!