Android 架構組件的最新進展

原創: Android [谷歌開發者]
原文鏈接:https://mp.weixin.qq.com/s/roOXiW3AbWVqe-mt8ahyPA

根據我們曾經做的調查,開發者們希望 Android 官方可以維護一些實用的組件庫和架構實踐,以降低中大型應用的開發門檻,這樣開發團隊就可以集中更多精力在實際業務的優化和改進上。

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

Android Jetpack 中的架構組件可幫助您設計穩健、可測試且易維護的應用。從最初發布的管理 Activity 和 Fragment 生命週期的 Lifecycle 庫和訪問 SQLite 數據庫的 Room 庫,後來推出了分頁 (Paging)、導航 (Navigation) 和管理後臺任務的 WorkManager 庫。

根據 2019 年最新的開發者調查中,70% 以上的專業開發者用過這五個庫當中的至少一個庫進行應用開發,接下來我們將用上、下兩篇文章爲大家介紹 Android 架構組件的最新更新:

在這裏插入圖片描述

數據綁定庫

數據綁定 (Data Binding) 庫是一種支持庫,藉助該庫,您可以使用聲明性格式 (而非程序化地) 將佈局中的界面組件綁定到應用中的數據源。數據綁定可以理解爲代碼和 XML 標記語言之間的橋樑。

更快的編譯速度
對開發者來說,處理界面中的數據綁定需要的時間成本不容忽視,我們現在將數據綁定註解處理的速度提高了 20%*。

Google 內部實測結果
如果您的工作涉及到協同開發,還有一個好消息,那就是我們增加了對分佈式構建緩存的支持。

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

android.databinding.incremental = true
和 Android Studio 更緊密地集成
實時生成類代碼
現在,給視圖中的某個控件賦予 ID, 它就會在綁定的類中成爲一個可用的字段。或者直接在 XML 中設置一個變量,並在視圖中訪問,代碼也能馬上給出對應的提示。這些都即時可用,無需編譯!
在這裏插入圖片描述
在這裏插入圖片描述
更好地支持重構
在 IDE 裏使用重構的方式修改函數名稱之後,XML 中會同步進行更新。
在這裏插入圖片描述
更好用的報錯信息
數據綁定出錯的信息可能一下子跳出來 1,000 條,這種尷尬將成爲過去。現在在構建輸出信息窗口中,數據綁定錯誤單獨成組,這樣開發者能更輕鬆地找到自己需要處理的錯誤信息。
在這裏插入圖片描述

有沒有更好的視圖訪問方式?
在這裏插入圖片描述
視圖訪問方法當然不止一種,但正如上圖所示的,在簡明、編譯安全和編譯速度上,各個方法總有取捨。那有沒有一種方法能一石 “三” 鳥呢?
即將到來!視圖綁定 (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 插件生成,如果開發者修改了某個佈局文件,會報錯的也會只有這個文件,100% 編譯安全。

處理生命週期

“ViewModel 和 SavedState 一樣嗎?ViewModel 會破壞 SavedState 嗎?”
——很多開發者會這麼問

基本上,開發者會通過 ViewModel 或着 SavedState 來保存自己的內容/狀態,當應用配置發生變化時再從 ViewModel 或者 SavedState 中取回保存的內容/狀態:

在這裏插入圖片描述

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

SavedState 會經由 System Server (一個獨立的進程) 保存內容 (序列化的數據),也就是說,它會無視進程的限制。

而 ViewModel 則一直運行於進程內,即便應用配置發生變化,只要進程還在,ViewModel 保存的內容就不會消失。但只要進程消失,ViewModel 裏的內容也會消失。

ViewModel 用於:
保留應用對網絡、數據庫的請求
當作大型對象的緩存

SavedState 用於:
UI 的狀態記錄,比如選擇區域和滾動距離等
導航狀態鍵值記錄

各取所長,聯手打造流暢體驗

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

現在用戶的 ViewModel 會在構造函數中接收一個 SavedStateHandle,這樣開發者就能在 ViewModel 中馬上訪問 SavedState。

而這個 SavedStateHandle 內部的邏輯也非常直白: 一個 Map 類的鍵值結構。當然,也提供了 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 友好的代碼
我們會持續確保 Kotlin 語言的首選開發語言地位。其中一個例子就是 liveData.observe 現在支持 lambda 表達式:

// lifecycle-livedata-ktx

liveData.observe(lifecycleOwner) { newValue ->
}

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

// lifecycle-livedata-ktx

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

// 現在
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)
}

而現在只需要一行:

// ViewModels initialization

val userViewModel: UserViewModel by viewModels()

強烈推薦:揭祕:如何化身BAT面試offer收割機?

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章