Coordinators簡介
2個月前,square開源了Coordinators。這個項目的作用在主頁的第一句話寫得很清楚:
Simple lifecycle for your MVWhatever on Android. No kidding.
講真,簡化Android開發中MV**模式里的生命周期。
項目的使用也十分簡單,首先讓你的界面控制層繼承Coordinator
。
所謂控制層:MVVM里就是ViewModel,MVP里就是Presenter
class Whaterver extends Coordinator {
@Override public void attach(View view) {
// Attach listeners, load state, whatever.
}
@Override public void detach(View view) {
// Unbind listeners, save state, go nuts.
}
}
然后把你的控制層和界面進行綁定:
// Create a factory for your Coordinators.
CoordinatorProvider coordinatorProvider; // @Nullable (View) -> Coordinator
// Bind a Coordinator to a View.
Coordinators.bind(view, coordinatorProvider);
// Bind a Coordinator to any child View added to a group.
Coordinators.installBinder(viewGroup, coordinatorProvider);
綁定方法可以看見,綁定的對象不是比較高級頁面對象Activity
或Fragment
,而是更底層的View
或者ViewGroup
。
Android的界面顯示組件
首先簡單介紹一下Android的各個界面顯示組件:
1.Activity
Android里最基本的頁面組件,基本上每一個全屏頁面都是一個Activity
。Activity
并不顯示具體的內容,而只是一個簡單的容器,容器內部包含了各種View
和ViewGroup
。
2.View
和ViewGroup
View
就是顯示的基本控件,包括按鈕,文本框,圖片框等等。ViewGroup
的性質類似html中的div,其內部包含了各種View
和ViewGroup
。然后整體被放進了Activity
中:
+------------------+
| Activity |
| |
| +-------+ |
| | View | |
| | Group | |
| +-------+ |
| |
+------------------+
最初Android的展示界面就是這兩種。隨著應用界面的復雜度不斷升高,加上單頁應用的體驗比多頁更加優秀,Activity內代碼也隨之不斷增多。
3.Fragmnet
為此,谷歌推出了Fragment,這個組件可以像Activity一樣包含ViewGroup,同時又能像ViewGroup一樣被添加到Activity中。這樣開發者只需要把原來繼承Activity的內容修改為繼承Fragment,然后通過配套的Api把多個Fragment添加到一個Activity中。就能快速的將一個多頁應用改造成一個單頁應用。
+--------------------+
| Activity |
| |
| +----------+ |
| | Fragment | |
| +----------+ |
| |
+--------------------+
+------------------+
| Fragment |
| |
| +-------+ |
| | View | |
| | Group | |
| +-------+ |
| |
+------------------+
同時開發者依然可以遵循原來的Activity開發習慣,繼續基于Fragment開發應用。
這看起來很美妙,但Android存在一個令人抓狂的概念——生命周期
生命周期
聲明周期描述的是一個頁面從打開到銷毀經歷的各個過程,在各個過程里系統都會通過方法告知開發者。就Activity來說,開發者主要關心的方法大概有:
onCreate() // 界面創建
↓
onResume() // 準備顯示
↓
onPostResume() // 顯示完成
↓
onPause() // 從屏幕消失
↓
onDestory() // 被系統銷毀
這只是大概,還有一些特殊情況,例如在被系統銷毀前再次打開應用,還會多觸發一些事件。但這種復雜度對于大多數人還在可以接受范圍內。
但是,在引入Fragment之后,
首先Fragment和Activity并不完全相同,在使用方面會有一些坑需要躲避;
其次由于Fragment也有生命周期的概念,一方面,Fragment需要跟隨Activity進行顯示隱藏;另一方面Fragment會被開發者動態的添加/移除,因此他又有自己需要獨立的生命周期事件:
有一個專門的github項目android-lifecycle整理了各個生命周期的關系
來感受一下:
對于生命周期,大部分情況下,開發者僅僅關注應用的打開和關閉事件。但引入Fragment后需要增加更多的開發測試成本。例如Fragment如果存在于翻頁組件中,當前頁被翻走后,我們可能會認為將會觸發Fragment的onPause事件,而實際上,觸發的是onHiddenChange事件。
封裝ViewGroup
回到最初Activity遇到的問題。我們不引入Fragment,而直接使用ViewGroup
+------------------+
| Activity |
| |
| +-------+ |
| | View | |
| | Group | |
| +-------+ |
| |
+------------------+
+------------------+
| ViewGroup |
| |
| +-------+ |
| | View | |
| | Group | |
| +-------+ |
| |
+------------------+
并且從面向Activity開發轉為面向ViewGroup開發。ViewGroup的生命周期事件只有兩個:onAttach
和onDetach
,分別在被添加到屏幕和被移除時調用。而遇到特殊的事件,我們就需要通過手動的方式從Activity中往ViewGroup里傳遞。對比Fragment
缺點:
- 舊的Activity無法方便遷移到Fragment里
- 需要手動傳遞特殊的聲明周期事件(例如onActivityResult)
優點:
- 因為僅有最簡單的生命周期,所以完全不會造成迷惑
- 不需要學習Fragment復雜的生命周期和Api
Coordinators
Coordinators項目實際上只有5個小文件,他做的僅僅是把ViewGroup的兩個生命周期提取到他的Coordinator類里,讓開發者面向Coordinator類來進行開發。
所以與其說他是一個框架,不如說是一種約束: 既然Activity里內容太多,那就只提供一個能把Activity中內容分隔開的組件,這個組件不需要有太復雜太全面的功能,而僅僅是一個引導的作用。經過他的約束,開發者自然會規范自己的代碼。
總結
使用Fragment或者ViewGroup孰優孰劣實際上還是需要具體場景結合分析。
Fragment是官方推出的框架,他的特點就是大、全、嚴謹;而Coordinators更像一個規范代碼的工具類。都可以解決顯示組件模塊化問題。
我們在開發中往往也會遇到類似的代碼框架上的問題,為了修復這些問題,或許我們也會去考慮寫一個更完善的框架,或者引入一個新的概念和組件。
而Coordinators告訴我們,當遇到這種問題我們或許可以通過代碼約束的角度來解決。設計一些方法對出現問題的根本進行約束,或許在功能上有所損失,但對于使用者來說,學習成本降低或許能帶來更好的效果。
相關閱讀: