Android 架構(gòu)組件的最新進(jìn)展 (上篇)

根據(jù)我們曾經(jīng)做的調(diào)查,開發(fā)者們希望 Android 官方可以維護(hù)一些實用的組件庫和架構(gòu)實踐,以降低中大型應(yīng)用的開發(fā)門檻,這樣開發(fā)團(tuán)隊就可以集中更多精力在實際業(yè)務(wù)的優(yōu)化和改進(jìn)上。

Jetpack 項目正是為了解決這些問題而誕生的,Jetpack 是一系列助力您更容易打造優(yōu)秀 Android 應(yīng)用的工具和組件,這些組件能幫助您遵循最佳實踐、免除編寫繁復(fù)的樣板代碼并簡化復(fù)雜任務(wù),從而使您可以專注于最核心的代碼邏輯。其中 androidx.* 庫與 Framework API 解耦,這能夠提供向后兼容的同時,也能更頻繁地更新。

Android Jetpack 中的架構(gòu)組件可幫助您設(shè)計穩(wěn)健、可測試且易維護(hù)的應(yīng)用。從最初發(fā)布的管理 Activity 和 Fragment 生命周期的Lifecycle 庫和訪問 SQLite 數(shù)據(jù)庫的Room 庫,后來推出了分頁 (Paging)、導(dǎo)航 (Navigation) 和管理后臺任務(wù)的WorkManager 庫。

根據(jù) 2019 年最新的開發(fā)者調(diào)查中,70% 以上的專業(yè)開發(fā)者用過這五個庫當(dāng)中的至少一個庫進(jìn)行應(yīng)用開發(fā),接下來我們將用上、下兩篇文章為大家介紹 Android 架構(gòu)組件的最新更新:

數(shù)據(jù)綁定庫

數(shù)據(jù)綁定 (Data Binding) 庫是一種支持庫,借助該庫,您可以使用聲明性格式 (而非程序化地) 將布局中的界面組件綁定到應(yīng)用中的數(shù)據(jù)源。數(shù)據(jù)綁定可以理解為代碼和 XML 標(biāo)記語言之間的橋梁。

更快的編譯速度
對開發(fā)者來說,處理界面中的數(shù)據(jù)綁定需要的時間成本不容忽視,我們現(xiàn)在將數(shù)據(jù)綁定注解處理的速度提高了 20%*。

  • Google 內(nèi)部實測結(jié)果。

如果您的工作涉及到協(xié)同開發(fā),還有一個好消息,那就是我們增加了對分布式構(gòu)建緩存的支持。

最后,數(shù)據(jù)綁定支持增量注解處理,能提升增量構(gòu)建的性能。但這個功能還停留在測試階段,所以請在 Gradle 配置文件中使用如下代碼手動打開:

android.databinding.incremental = true

和 Android Studio 更緊密地集成

實時生成類代碼
現(xiàn)在,給視圖中的某個控件賦予 ID, 它就會在綁定的類中成為一個可用的字段?;蛘咧苯釉?XML 中設(shè)置一個變量,并在視圖中訪問,代碼也能馬上給出對應(yīng)的提示。這些都即時可用,無需編譯!


更好地支持重構(gòu)
在 IDE 里使用重構(gòu)的方式修改函數(shù)名稱之后,XML 中會同步進(jìn)行更新。

更好用的報錯信息
數(shù)據(jù)綁定出錯的信息可能一下子跳出來 1,000 條,這種尷尬將成為過去?,F(xiàn)在在構(gòu)建輸出信息窗口中,數(shù)據(jù)綁定錯誤單獨成組,這樣開發(fā)者能更輕松地找到自己需要處理的錯誤信息。

有沒有更好的視圖訪問方式?

視圖訪問方法當(dāng)然不止一種,但正如上圖所示的,在簡明、編譯安全和編譯速度上,各個方法總有取舍。那有沒有一種方法能一石 "三" 鳥呢?
即將到來!視圖綁定 (View Binding)
給出 ID 即可自動生成綁定類代碼且能保證編譯安全,能做到一石 "三" 鳥的視圖綁定可在 Android Studio 3.6 Canary 11 或更新版本中用得上。

<!-- profile.xml -->
<LinearLayout>
    <TextView android:id="@id/title"/>
    <ImageView android:id="@id/photo"/>
</LinearLayout>



class ProfileActivity:AppCompatActivity {
    override fun onCreate(savedInstanceState:Bundle?) {
        val binding = ProfileBinding.inflate(layoutInflater)
        setContentView(binding.root)
        // binding.title:TextView
        // binding.photo:ImageView
    }
}

△ 在生成的綁定類 inflate 之后,即可運行 setContentView,如果綁定的某個類型的控件不存在則無法編譯。是時候告別 findViewById 了

所有的這些綁定類均由 Gradle 插件生成,如果開發(fā)者修改了某個布局文件,會報錯的也會只有這個文件,100% 編譯安全。

處理生命周期

"ViewModel 和 SavedState 一樣嗎?ViewModel 會破壞 SavedState 嗎?"
——很多開發(fā)者會這么問

基本上,開發(fā)者會通過 ViewModel 或著 SavedState 來保存自己的內(nèi)容/狀態(tài),當(dāng)應(yīng)用配置發(fā)生變化時再從 ViewModel 或者 SavedState 中取回保存的內(nèi)容/狀態(tài):



如果只這樣粗略地理解的話,ViewModel 和 SavedState 其實是一回事。然而并不是這樣的。

SavedState 會經(jīng)由 System Server (一個獨立的進(jìn)程) 保存內(nèi)容 (序列化的數(shù)據(jù)),也就是說,它會無視進(jìn)程的限制。

而 ViewModel 則一直運行于進(jìn)程內(nèi),即便應(yīng)用配置發(fā)生變化,只要進(jìn)程還在,ViewModel 保存的內(nèi)容就不會消失。但只要進(jìn)程消失,ViewModel 里的內(nèi)容也會消失。

ViewModel 用于:

  • 保留應(yīng)用對網(wǎng)絡(luò)、數(shù)據(jù)庫的請求
  • 當(dāng)作大型對象的緩存

SavedState 用于:

  • UI 的狀態(tài)記錄,比如選擇區(qū)域和滾動距離等
  • 導(dǎo)航狀態(tài)鍵值記錄

各取所長,聯(lián)手打造流暢體驗

// SavedStateHandle
class UserViewModel(val handle: SavedStateHandle) : ViewModel() {
}

現(xiàn)在用戶的 ViewModel 會在構(gòu)造函數(shù)中接收一個 SavedStateHandle,這樣開發(fā)者就能在 ViewModel 中馬上訪問 SavedState。

而這個 SavedStateHandle 內(nèi)部的邏輯也非常直白: 一個 Map 類的鍵值結(jié)構(gòu)。當(dāng)然,也提供了 LiveData 供訪問,只不過在這里使用的是 MutableLiveData (因為 SavedState 是可變的)。


// map-like object
val handle : SavedStateHandle

// read
val myValue : Int = handle.get("key")

// write
handle.put("key", newValue)

// or
val liveData : MutableLiveData<Int> = handle.getLiveData("key")

// observe as usual
liveData.observe (lifecycleOwner) { value -> }

// write
liveData.value = newValue

更 Kotlin 友好的代碼
我們會持續(xù)確保 Kotlin 語言的首選開發(fā)語言地位。其中一個例子就是 liveData.observe 現(xiàn)在支持 lambda 表達(dá)式:

// lifecycle-livedata-ktx

liveData.observe(lifecycleOwner) { newValue ->
}

另一個例子則是 LiveData 不再需要使用靜態(tài)的 Transformations.map 方法:

// lifecycle-livedata-ktx

// 以前
val mapped = Transformations.map(liveData) {
    user -> user.name 
}

// 現(xiàn)在
val mapped = liveData.map { user -> user.name }

ViewModel 的初始化也大幅精簡,以前您可能需要這么操作:


// ViewModels initialization

lateinit var userViewModel: UserViewModel

fun onCreate(bundle: Bundle?) {
    userViewModel = ViewModelProviders.of(this)
        .get(UserViewModel::class.java)
}

而現(xiàn)在只需要一行:

// ViewModels initialization

val userViewModel: UserViewModel by viewModels()

導(dǎo)航

導(dǎo)航 (Navigation) 是一套管理應(yīng)用內(nèi) UI 流程的 Jetpack 代碼庫,現(xiàn)已發(fā)布了 2.1 的穩(wěn)定版,與此同時下一個版本也已經(jīng)出現(xiàn)在了不遠(yuǎn)的前方,接下來我們會:

  • 在導(dǎo)航中提供成組 (Scoped) ViewModel,比如一套登錄流程的界面集合就可以用一個 ViewModel 來管理

  • 使用 URI 直接導(dǎo)航

  • 對話框可以做為導(dǎo)航目標(biāo)

  • 更好地對動態(tài)功能做出支持

請大家保持對本次連載的關(guān)注,我們會在下篇中為大家介紹分頁庫、Room 持久性庫和 WorkManager 的更新進(jìn)展。您也可以觀看 ?下面的視頻? 重溫我們對架構(gòu)組件進(jìn)展的介紹。

希望在了解完架構(gòu)組件的最新進(jìn)展后,大家能在其中找到適合自己應(yīng)用的功能。如果對架構(gòu)組件有疑問或者建議,歡迎在評論區(qū)和我們分享。

點擊這里進(jìn)一步了解 Android Jetpack

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容