Google I/O :Android Jetpack 最新變化(四)Compose
theme: devui-blue highlight: atelier-sulphurpool-light
前言
本系列文章從 Architecture,UI,Performance 和 Compose 這四個方向帶大家瞭解本次 I/O 上 Jetpack 的最新內容。
- Google I/O :Android Jetpack 最新變化(一)Architecture
- Google I/O :Android Jetpack 最新變化(二)Performance
- Google I/O :Android Jetpack 最新變化(三)UI
- Google I/O :Android Jetpack 最新變化(四)Compose
本文是最終篇:Compose 篇。
今年 I/O 大會上關於 Compose 的主題分享明顯增多了,這也表明了谷歌對於 Compose 推廣之重視。目前 GooglePlay Top1000 的應用中使用 Compose 的已經超過了 100 個,其中不乏一些領域頭部應用,Compose 的穩定性和成熟度也藉機得到了驗證。
讓我們看看 Compose 最新的 1.2 Beta 版本帶來哪些新內容。
1. Material 3
新增的 Compose.M3 庫,可以幫助我們開發符合 Material You 設計規範的的 UI 介面。
groovy
implementation "androidx.compose.material3:material3:1.0.0-alpha10"
implementation "androidx.compose.material3:material3-window-size-class:1.0.0-alpha10"
Material3 強調顏色的個性化和動態切換,Compose.M3 引入 ColorScheme 類自定義配色方案:
```kotlin
val AppLightColorScheme = lightColorScheme (
primary = Color(...),
// secondary、tertiary 等等
// 具有淺色基準值的 ColorScheme 例項
)
val AppDarkColorScheme = darkColorScheme( // primary、secondary、tertiary 等等 // 具有深色基準值的 ColorScheme 例項 )
val dark = isSystemInDarkTheme() val colorScheme = if (dark) AppDarkColorScheme else AppLightColorScheme
// 將 colorScheme 作為引數傳遞給 MaterialTheme。 MaterialTheme ( colorScheme = colorScheme, // 字型 ) { // 應用內容 } ``` 上面是 MaterialTheme 通過 ColorScheme 配置不同主題顏色的例子,可以看到這與 Compose.M2 中 Colors 用法區別不大, 但是 ColorScheme 可定義的顏色槽(Primary,Secondary,Error 等MD顏色常量)種類更多,而且還可以支援 DynamicColor 動態配色。
DynamicColor 是 Material3 的重要特色,在 Android12 及以上裝置中,可以實現應用的顏色跟隨桌布變化。如今 Compose 中也可以實現這個效果
kotlin
// Dynamic color is available on Android 12+
val dynamicColor = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S
val colorScheme = when {
dynamicColor && darkTheme -> dynamicDarkColorScheme(LocalContext.current)
dynamicColor && !darkTheme -> dynamicLightColorScheme(LocalContext.current)
darkTheme -> DarkColorScheme
else -> LightColorScheme
}
如上,Compose 通過 dynamicXXXColorScheme 設定的顏色,無論是亮色還是暗色主題,都可以跟隨使用者設定的桌布而變化:
更多參考:http://juejin.cn/post/7064410835422019615
2. Nested Scrolling Interop
Compose 支援與傳統檢視控制元件進行互操作,便於我們階段性的引入 Compose 到專案中。但是在涉及到帶有 Nested Scrolling 事件分發的場景中(例如 CoordinatorLayout ),會發生事件無法正常傳遞的相容性問題,在 1.2 中對於此類問題進行了修復,無論是 CoordinatorLayout 內嵌 Composable , 或者在 Composable 中使用 Scrolling View 控制元件,事件傳遞都會更加平順:
http://android-review.googlesource.com/c/platform/frameworks/support/+/2004590
http://android-review.googlesource.com/c/platform/frameworks/support/+/2038823
3. Downloadable Fonts
Android 8.0(API level 26)起支援了對可下載的谷歌字型的使用,允許通過程式碼動態請求一個非內建字型檔案。在 Compose 1.2 對此功能也進行了支援,注意這個功能需要基於 GMS 服務。
groovy
implementation "androidx.compose.ui:ui-text-google-fonts:1.1.1"
使用時,首先使用 FontProvider 定義字型請求資訊
```kotlin
@OptIn(ExperimentalTextApi::class)
val provider = GoogleFont.Provider(
providerAuthority = "com.google.android.gms.fonts",
providerPackage = "com.google.android.gms",
certificates = R.array.com_google_android_gms_fonts_certs
)
然後,使用此 Provider 定義 FontFamily,接著在 Composable 應用即可,
val fontName = GoogleFont(“Lobster Two”)
val fontFamily = FontFamily( Font(googleFont = GoogleFont(name), fontProvider = provider) )
Text( fontFamily = fontFamily, text = "Hello World!" ) ```
4. Lazy Grid
Compose 1.2 中進一步優化了 LazyRow 和 LazyColumn 的效能,並在此基礎上新增了 LazyGrid 用來實現需求中常見的網格佈局效果。Lazy Grid 在 1.0.2 就已經引入,如今 1.2 中對 API 進行調整並使之達到穩定。
以 LazyVerticalGrid 為例,我們可以通過 GridCells.Fixed 設定每行單元格的數量:
```kotlin val data = listOf("Item 1", "Item 2", "Item 3", "Item 4", "Item 5")
LazyVerticalGrid( columns = GridCells.Fixed(3), contentPadding = PaddingValues(8.dp) ) {//this: LazyGridScope items(data.size) { index -> Card( modifier = Modifier.padding(4.dp), backgroundColor = Color.LightGray ) { Text( text = data[index], textAlign = TextAlign.Center ) } } } ``` 此外,也可以通過 GridCells.Adaptive() 通過制定單元格大小決定每行的數量。此時,所有單元格都會以 Adaptive 中的值設定統一的 width。
LazyGridScope 像 LazyListScope 一樣也提供了 item, items, itemsIndexed 等方法佈局子項。另外 LazyGridState 中的方法也基本上對齊了 LazyListState。
5. Tools
在工具方面,Android Studio 為 Compose 的開發除錯提供了更多實用功能。
@Preview & Live Edit
1.2.0 中的 @Preview 可以作為元註解使用,修飾其他自定義註解 ```kotlin @Preview(showBackground = true) @Preview(showBackground = true, uiMode = UI_MODE_NIGHT_YES) annotation class MyDevices()
@MyDevices @Composable fun Greeting() { ... } ``` 如上,我們可以通過自定義註解可以複用 @Preview 中的各種配置,減少為了預覽而寫的模板程式碼。
說到預覽,Android Studio 一直致力於提升預覽效率,Android Studio Arctic Fox 曾引入 Live literals 功能,對於程式碼中 Int,String,Color,Dp,Boolean 等常見型別的字面值的修改,無需編譯即可在預覽畫面中實時更新。本次大會上帶來了升級版的 Live Edit,它需要使用最新的 Android Studio Electric Eel 中開啟。不僅僅是字面值,它可以讓任意程式碼的修改(函式簽名變動之類的修改不行),在預覽視窗或者你的裝置上立即生效,幾乎實現了前端一般的開發體驗,是本次大會令我驚喜的功能,它將大幅提高 Compose 的開發和除錯效率。
Layout Inspector & Recomposition Counts
我們在傳統檢視開發中經常使用 Layout Inspector 觀察檢視結構, Compose 雖然基於 Composable 函式構建 UI ,但同樣也得到了 layout Inspector 的支援,它可以幫助我們檢視 Composition 檢視樹的佈局。
此外,本次 I/O 還介紹了 Layout Inspector 的一個新功能 Recomposition Counts,我們知道不必要的重組會拖慢 Compose UI 的重新整理效能,藉助這個新工具,我們可以在 IDE 中除錯和觀察 Composable 重組次數,幫助我們及時發現和優化不符合預期的多餘重組。
Animation Preview
Android Studio 增加了對 Compose 動畫效果實時預覽。在動畫預覽視窗中,每個動畫的狀態值會以多軌道的形式呈現,我們可以檢視特定時間點下的每個動畫值的確切值,並且可以暫停、迴圈播放動畫、快進或放慢動畫,以便在動畫過渡過程中除錯動畫。
Compose 的動畫 API 數量眾多,目前並非所有的 API 都支援預覽,IDE 會自動檢查程式碼中可以進行預覽的動畫,並新增 Start Animation Inspection 圖示,便於開發者發現和使用
6. 適應多種螢幕尺寸
Compose 正逐漸成為 Android 的首選 UI 開發方案,所以為了覆蓋儘可能多的使用場景,Compose 第一時間對各種螢幕尺寸下(手機,平板,電腦,摺疊屏)的 UI 開發進行了支援。 在具體開發中,我們需要先定義 WindowSizeClass 對各種螢幕型別分類,推薦分為三類:
當螢幕尺寸因為裝置摺疊等發生變化時,Compose 會自動響應 onConfigurationChanged 觸發重組,重組中我們根據當前螢幕尺寸轉換為對應的 WindowSizeClass
```kotlin
@Composable
fun Activity.rememberWindowSizeClass(): Pair
val heightWindowSizeClass = when {
windowDpSize.height < 480.dp -> WindowHeightSizeClass.Compact
windowDpSize.height < 900.dp -> WindowHeightSizeClass.Medium
else -> WindowHeightSizeClass.Expanded
}
return widthWindowSizeClass to heightWindowSizeClass
} ``` 接下來,我們就可以面向 WindowSizeClass 進行 Composable 佈局了,這樣做的好處是,無需關心具體的 width/height 數值,更不需要關心當前裝置型別是平板還是手機,因為未來,硬體種類的界限將越來越模糊,所以最合理的分類方式是 WindowSizeClass。
```kotlin @Composable fun MyApp(widthSizeClass: WindowWidthSizeClass) { // 非 Compact 型別螢幕時,不顯示 AppBar val showTopAppBar = widthSizeClass != WindowWidthSizeClass.Compact
// MyScreen 不依賴 WindowSizeClass,只需要知道是否顯示 showTopAppBar,關注點分離
MyScreen(
showTopAppBar = showTopAppBar,
/* ... */
)
} ``` 當然我們可以使用 Android Studio 便利的預覽功能,同時檢視多種螢幕尺寸下的顯示效果
最佳實踐: Now In Android
最後推薦一個谷歌剛剛開源的新專案 Now In Android。 Now in Android 是 Android 官方的技術部落格,分享技術文章和影片,如今這個部落格有了自己的客戶端,並在 Github 進行了開源,http://github.com/android/nowinandroid。
開發者通過 App 可以更好地追蹤 Android 最新的技術動向,更重要的是它本身就是一個 Android Jetpack 的最佳實踐,在技術上它具有以下特點: - 基於 Jetpack Compose 實現 UI - 基於 Material3 的視覺樣式和主題 - 對不同尺寸的螢幕進行了支援,能夠自適應佈局 - 整體架構遵循官方文件 UDF 正規化 - 基於 Kotlin Flow 實現響應式程式設計模型 - 遵循 Offline first 設計原則,基於 Room 以及 Proto DataSotre 實現本地資料來源, - 基於 WorkManager 實現遠端/本地資料來源之間的同步
另外,GIthub 上還貼心了附上了架構設計文件,方便你瞭解它的開發思路,Now in Android 已經預定上架 GooglePlay, 相對於 Jetpack 的其他 Demo,它是更加真實和完善,非常值得大家研究和學習。
- Android Studio Electric Eel 起支援手機投屏
- Compose 為什麼可以跨平臺?
- 一看就懂!圖解 Kotlin SharedFlow 快取系統
- 深入淺出 Compose Compiler(2) 編譯器前端檢查
- 深入淺出 Compose Compiler(1) Kotlin Compiler & KCP
- Jetpack MVVM七宗罪之三:在 onViewCreated 中載入資料
- 為什麼說 Compose 的宣告式程式碼最簡潔 ?Compose/React/Flutter/SwiftUI 語法對比
- Compose 型別穩定性註解:@Stable & @Immutable
- Fragment 這些 API 已廢棄,你還在使用嗎?
- 告別KAPT!使用 KSP 為 Kotlin 編譯提速
- 探索 Jetpack Compose 核心:深入 SlotTable 系統
- 盤點 Material Design 3 帶來的新變化
- Compose 動畫邊學邊做 - 夏日彩虹
- Google I/O :Android Jetpack 最新變化(二) Performance
- Google I/O :Android Jetpack 最新變化(一) Architecture
- Google I/O :Android Jetpack 最新變化(四)Compose
- Google I/O :Android Jetpack 最新變化(三)UI
- 一文看懂 Jetpack Compose 快照系統
- 聊聊 Kotlin 代理的“缺陷”與應對
- AAB 扶正!APK 再見!