本次分享有錄屏,可查看 BaguTree 組織地址,感謝校長、強哥、超哥提供的分享平台:http://jetpack.net.cn/#/blog/all[1]
目錄:
本期分享目標:讓還在觀望的開發者們可以沒有顧慮的用上 Compose
在與一些開發者溝通的過程中發現,有很多開發者並不知道怎麼接入 Compose,有的可能嘗試接入了,但會報各種奇奇怪怪的編譯錯誤,如果在工程接入這塊就發生問題了的話,這簡直就是還沒入門就勸退。也有的開發者以為需要 AGP 7.0 以上才能使用 Compose,對於目前現存的老工程無法接入。但到底是哪個版本才開始支持,還是有很多人不清楚。一、Compose 是什麼Jetpack Compose 是用於構建原生 Android 界面的新工具包。它使用更少的代碼、強大的工具和直觀的 Kotlin API,可以幫助您簡化並加快 Android 界面開發,打造生動而精彩的應用。它可讓您更快速、更輕鬆地構建 Android 界面
1、更少的代碼以及更快速的開發例如一個列表控件:
LazyColumn() { items(apkInfos, key = { apk -> apk.packageName!! }) { apk -> AppInfoItem(apk) {} }}val rv = findViewById<RecyclerView>(R.id.rv)val adapter = AppListAdapter()rv.layoutManager = LinearLayoutManager(this)rv.adapter = adapter// 1、要寫 Adapter 類class AppListAdapter() : ListAdapter<ApkInfo, AppListAdapter.AppListViewHolder>(AppListDiff) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AppListViewHolder { ... } override fun onBindViewHolder(holder: AppListViewHolder, position: Int) { ... }}// 2、要寫 ViewHolder 類class AppListViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { ...}// 3、要寫 Diff 類private object AppListDiff : DiffUtil.ItemCallback<ApkInfo>() { ...}// 4、xml 部分代碼2、直觀Compose 使用聲明式 API,可以顯示聲明組件與狀態,並且可以很直觀的查看狀態在組件上的流轉。
3、強大的兼容性原生可以嵌套 Compose,Compose 可以嵌套原生,並且可以無縫的使用 Jetpack 組件,例如 ViewModel、LiveData、Flow 等
Compose 中嵌套原生 View 原理
二、如何學習 Compose學習一門框架的幾個步驟:
官方學習資料:
了解官方走向:Jetpack Compose 路線圖[3]了解 Compose 的樣貌:使用 Jetpack Compose 更快地打造 更出色的應用[4]官方教程文檔 : Jetpack Compose 使用入門[5]跟着官方動手實踐:Compose Codelabs[6]參考官方寫的應用:Compose-Sample[7]Compose 補充庫,有很多 UI 框架:Accompanist[8]博文資料:
官方公眾號:Jetpack Compose(https://mp.weixin.qq.com/mp/homepage?__biz=Mzk0NDIwMTExNw==&hid=13&sn=92a0fbf8f1b75db9d1db83e858da83fd&scene=18)fundroid Compose 系列(https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=Mzg5MzYxNTI5Mg==&scene=1&album_id=1846144099200876545&count=3&token=2135010104&lang=zh_CN#wechat_redirect)書籍:
購買鏈接:《Jetpack Compose 從入門到實戰》(王鵬,關振智,曾思淇)[11]三、用示例了解 Compose 重組沉思錄 | 如何優化 Compose 的性能?通過「底層原理」尋找答案。探索 Compose 內核:深入 SlotTable 系統實踐 | Jetpack Compose 中的狀態管理深入詳解 Jetpack Compose | 實現原理(https://mp.weixin.qq.com/s?__biz=Mzk0NDIwMTExNw==&mid=100002002&idx=1&sn=1e13c610ced87dfa209edb72bdecfd96&scene=19&token=2135010104&lang=zh_CN#wechat_redirect)深入詳解 Jetpack Compose | 優化 UI 構建(https://mp.weixin.qq.com/s?__biz=Mzk0NDIwMTExNw==&mid=100002046&idx=1&sn=f1a0a2508a2ded77f7eb853b0e9e518d&scene=19&token=2135010104&lang=zh_CN#wechat_redirect)引用朱濤老師文章的示例:
優化前:
輸出結果:MainActivity: MainScreen startMainActivity: Greeting start InitMainActivity: Greeting end InitMainActivity: MainScreen end等待 1秒MainActivity: MainScreen start // 重組MainActivity: Greeting start Modified // 重組MainActivity: Greeting end Modified // 重組MainActivity: MainScreen end // 重組優化後:
image.png輸出結果:MainActivity: MainScreen startMainActivity: Greeting start InitMainActivity: Greeting end InitMainActivity: MainScreen end等待 1秒MainActivity: Greeting start Modified // 重組MainActivity: Greeting end Modified // 重組一句話總結:狀態讀取發生在哪個 Scope,狀態更新的時候,哪個 Scope 就發生重組。
上面的代碼段就是採用 lambda 延遲到 Greeting 方法來讀取 state.value 值,將重組限制在 Greeting 這個可組合項的作用域中。
四、Compose 的性能相比 XML , Compose 性能到底怎麼樣?- 掘金[12]Google I/O : Jetpack Compose 中常見的性能問題 - 掘金[13]Jetpack Compose 筆記(3) - 重組的性能風險[14]4.1 Compose 與原生啟動性能比較
結論:Compose 的冷啟動略遜於原生,兩者相差 124ms,但在熱啟動與溫啟動狀態下,Compose 性能又優於原生
4.2、Compose Baseline Profiles 加持官方文檔:Improving performance - Baseline Profiles[15]Baseline Profiles 在 Compose 中的應用說一說Android的Dalvik,ART與JIT,AOT[16]
結論:有 Profiles 加持時,啟動優化了 30ms
注意:
通過查看 AGP 源碼了解到,Baseline Profiles 的 task 只在 AGP 7.0 版本才支持,7.0 以下的 AGP 跑 Compose項目時,享受不到 Baseline Profiles 帶來的優化五、Compose 與 AGP(android-gradle-plugin)、KGP(kotlin-gradle-plugin) 的關係
Compose、AGP、KGP 依賴關係圖
基於 KCP(kotlin compiler plugin) 的插件有:



Kotlin 插件的工作過程(圖來自朱濤老師文章)
5.1 Compose 版本最佳配置:// project build.gradlebuildscript { ext.kotlin_version = '1.6.10' ext.compose_version = '1.1.0' ... dependencies { ... classpath 'com.android.tools.build:gradle:4.1.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" }}// app build.gradleandroid { ... buildFeatures{ compose true } // 重點:覆蓋掉 AGP 中的默認配置 composeOptions{ kotlinCompilerVersion "$compose_version" kotlinCompilerExtensionVersion "$kotlin_version" } }
Compose 與 Kotlin 的兼容性對應關係[17]
5.2 Compose 在 AGP 不同版本的表現AGP 4.2.0 以下不支持正式版本的 Compose。在查看 AGP 4.1.0 時,該版本內置的 compose-compiler 依賴是 androidx.compose:compiler,而正式版本的依賴是 androidx.compose.compiler:compilerAGP 4.2.0 開始支持正式版本的 Compose。可根據 composeOptions 來自由配置 compose 版本,但版本需要參考兼容性文檔AGP 7.0 以下不支持 ArtProfileTask,這會導致無法生成 baseline.prof 文件,進而享受不到 Baseline Profiles 帶來的性能優化,結果就是性能不佳AGP 7.0 開始支持正式版 Compose 與 Baseline Profiles六、Compose 對編譯速度的影響Kotlin 編譯之路 「JAVA編譯器」[18]Kotlin 編譯之路 「Kotlin編譯器」[19]Jetpack Compose 導致的編譯劣化 | KCP 簡介 - 掘金[20]如果反編譯過 Compose 項目的話,你會發現代碼裡面有各種在編譯期間自動插入的 composer 代碼:
然後再來探討下,compose compiler 到底耗不耗時?需不需要去重點關注?我的總結是:
耗時是肯定的,但是不是痛點,我覺得得看項目結構,當項目採用殼工程+組件化方式開發,module 的耗時早就被打 aar 給均攤掉了,在主工程集成時,並不會影響編譯耗時七、Compose 跨平台現狀GitHub - JetBrains/compose-jb[21]
Compose 跨平台現狀圖
iOS 、Mac 端跨平台初見端倪,但目前還是實驗階段:
總結業務開發上,目前 Android 技術發展已經進入存量階段,現在已經很難再出現一款框架或是技術,來顛覆我們項目的生產,Compose 的推出,無疑是給 Android 生態增添了一份生機。
對於要不要使用 Compose 這個問題,我的建議是:先嘗試了解,學習官方文檔,然後嘗試寫一些 Demo,對照着公司的項目,用 Compose 去仿寫幾個頁面,如果整體問題不大的話,可以嘗試對公司項目的二三級頁面進行改造,然後通過性能監控或是用戶反饋的方式,來收集一些意見。
不過話也說回來,Jetpack Compose 容器依然是一個 ViewGroup,沒有脫離原生 View 體系,我覺得,問題應該不會太大,最多就是代碼使用不當,重組作用域擴大,導致頁面卡頓,但這種在開發期間是可以通過調試和監控可發現的,所以,大家趕緊用起來吧。
參考資料[1]http://jetpack.net.cn/#/blog/all: http://jetpack.net.cn/#/blog/all
[2]為什麼採用 Compose: https://developer.android.com/jetpack/compose/why-adopt?hl=zh-cn
[3]Jetpack Compose 路線圖: https://developer.android.com/jetpack/androidx/compose-roadmap
[4]使用 Jetpack Compose 更快地打造 更出色的應用: https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.android.google.cn%2Fjetpack%2Fcompose
[5]Jetpack Compose 使用入門: https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.android.google.cn%2Fjetpack%2Fcompose%2Fdocumentation
[6]Compose Codelabs: https://link.juejin.cn/?target=https%3A%2F%2Fcodelabs.developers.google.com%2F%3Fcat%3DAndroid%26text%3DCompose
[7]Compose-Sample: https://link.juejin.cn/?target=https%3A%2F%2Fgithub.com%2Fandroid%2Fcompose-samples
[8]Accompanist: https://link.juejin.cn/?target=https%3A%2F%2Fgoogle.github.io%2Faccompanist%2F
[9]Compose 博物館文檔: https://jetpackcompose.cn/docs/
[10]Compose 博物館開源項目: https://jetpackcompose.cn/docs/open-source-project/compose-douban
[11]《Jetpack Compose 從入門到實戰》(王鵬,關振智,曾思淇): https://item.jd.com/13290169.html
[12]相比 XML , Compose 性能到底怎麼樣?- 掘金: https://juejin.cn/post/7008522702835154980
[13]Google I/O : Jetpack Compose 中常見的性能問題 - 掘金: https://juejin.cn/post/7097066597222711327
[14]Jetpack Compose 筆記(3) - 重組的性能風險: https://chenhe.me/post/jetpack-compose-notes3-recompose-performance-risk/
[15]Improving performance - Baseline Profiles: https://developer.android.com/topic/performance/baselineprofiles#measuring-improvements
[16]說一說Android的Dalvik,ART與JIT,AOT: https://zhuanlan.zhihu.com/p/53723652
[17]Compose 與 Kotlin 的兼容性對應關係: https://developer.android.com/jetpack/androidx/releases/compose-kotlin
[18]Kotlin 編譯之路 「JAVA編譯器」: https://zhuanlan.zhihu.com/p/76140170
[19]Kotlin 編譯之路 「Kotlin編譯器」: https://zhuanlan.zhihu.com/p/76622754
[20]Jetpack Compose 導致的編譯劣化 | KCP 簡介 - 掘金: https://juejin.cn/post/7115653622926409759
[21]GitHub - JetBrains/compose-jb: https://github.com/JetBrains/compose-jb