根據我們曾經做的調查,開發者們希望 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()
複製程式碼
導航
導航 (Navigation) 是一套管理應用內 UI 流程的 Jetpack 程式碼庫,現已釋出了 2.1 的穩定版,與此同時下一個版本也已經出現在了不遠的前方,接下來我們會:
- 在導航中提供成組 (Scoped) ViewModel,比如一套登入流程的介面集合就可以用一個
- ViewModel 來管理
- 使用 URI 直接導航
- 對話方塊可以做為導航目標
- 更好地對動態功能做出支援
請大家保持對本次連載的關注,我們會在下篇中為大家介紹分頁庫、Room 永續性庫和 WorkManager 的更新進展。您也可以觀看 ☟下面的視訊☟ 重溫我們對架構元件進展的介紹。
騰訊視訊連結: v.qq.com/x/page/g300…
Bilibili 視訊連結: www.bilibili.com/video/av711…
希望在瞭解完架構元件的最新進展後,大家能在其中找到適合自己應用的功能。如果對架構元件有疑問或者建議,歡迎在評論區和我們分享。
點選這裡進一步瞭解 Android Jetpack