Android架構元件簡介
Android在2005年被引入世界,在這12年的存在中,該平臺取得了驚人的成功,成為安裝最多的移動作業系統。在此期間,已經推出了14個不同版本的作業系統,Android總是變得更加成熟。然而,平臺的一個非常重要的領域仍然被忽略:標準的架構模式,能夠處理平臺特性,並且足夠簡單,以便普通開發人員理解和採用。
好吧,遲到總比沒有好。在最後的Google I / O中,Android團隊最終決定解決這個問題並回應來自世界各地的開發人員的反饋,宣佈正式推薦Android應用程式架構並提供實現它的構建塊:新架構元件。更好的是,他們設法做到了這一點,同時又沒有損害我們都知道和喜愛的系統的開放性。

架構元件
在本教程中,我們將探討由Android團隊在谷歌I / O提出的標準化體系結構,並期待在新的體系結構元件的主要元素: Lifecycle
, ViewModel
, LifeData
,和 Room
。我們不會過多關注程式碼,而是關注這些主題背後的概念和邏輯。我們還將看一些簡單的片段,所有片段都是用Kotlin編寫的,這是一種現在由Android正式支援的神奇語言。
1. 什麼是Android缺失?
如果您剛剛開始作為開發人員的旅程,您可能無法確切地知道我在說什麼。畢竟,應用程式架構起初可能是一個模糊的主題。但請相信我,你很快就會了解它的重要性!隨著應用程式的增長和變得越來越複雜,其架構將變得越來越重要。它可以讓你的作品成為幸福或生活地獄。
應用架構
粗略地說,應用程式體系結構是一個需要在開發過程開始之前制定的一致計劃。該計劃提供瞭如何組織和捆綁不同應用程式元件的對映。它提出了在開發過程中應遵循的準則,並強制做出一些犧牲(通常與更多類和樣板相關),最終將幫助您構建一個更易於測試,可擴充套件和可維護的編寫良好的應用程式。
軟體應用程式體系結構是定義滿足所有技術和操作要求的結構化解決方案的過程,同時優化常見的質量屬性,如效能,安全性和可管理性。它涉及基於各種因素的一系列決策,每個決策都會對應用程式的質量,效能,可維護性和整體成功產生相當大的影響。
- Microsoft的軟體架構和設計指南
良好的架構需要考慮很多因素,尤其是系統特性和限制。有許多不同的建築解決方案,所有這些都有利有弊。但是,一些 關鍵概念 在所有願景之間都很常見。
老錯誤
在最後一個Google I / O之前,Android系統不建議任何特定的架構用於應用程式開發。這意味著你可以完全自由地採用任何模型:MVP,MVC,MVPP,甚至根本沒有模式。最重要的是,Android框架甚至沒有為系統本身建立的問題提供本機解決方案,特別是元件的生命週期。

Google IO 2017的好訊息
因此,如果您想在應用程式上採用Model View Presenter模式,則需要從頭開始提出自己的解決方案,編寫大量樣板程式碼,或者在沒有官方支援的情況下采用庫。缺乏標準會導致許多編寫得很糟糕的應用程式,其程式碼庫難以維護和測試。
正如我所說,這種情況多年來一直受到批評。事實上,我最近寫了一篇關於這個問題以及如何在我的 如何在Android 系列 上採用模型檢視演示器 來解決它的問題 。但重要的是,經過12年的漫長歲月,Android團隊最終決定傾聽我們的抱怨並幫助解決這個問題。
2. Android架構
新的 Android體系結構指南 定義了一個好的Android應用程式應該遵循的一些關鍵原則,併為開發人員提供了一個安全的途徑來建立一個好的應用程式。但是,該指南明確指出所提出的路線不是強制性的,最終決定是個人的; 開發人員應該決定採用哪種型別的架構。
根據該指南,一個好的Android應用程式應該提供一個牢固 的關注點分離, 並從一個模型驅動UI。任何不處理UI或作業系統互動的程式碼都不應該在Activity或Fragment中,因為儘可能保持它們乾淨將允許您避免許多與生命週期相關的問題。畢竟,系統可以隨時銷燬活動或碎片。此外,資料應由與UI隔離的模型處理,從而處理生命週期問題。
新推薦的架構
Android推薦的架構無法在我們所知的標準模式中輕鬆標註。它看起來像一個模型檢視控制器模式,但它與系統的架構密切相關,很難使用已知的約定標記每個元素。但這並不重要,因為重要的是它依賴於新的架構元件來建立關注點分離,具有出色的可測試性和可維護性。而且更好的是,它很容易實現。
要了解Android團隊提出的建議,我們必須瞭解架構元件的所有元素,因為它們將為我們帶來繁重的工作。有四個組成部分,每一個特定的角色: Room
, ViewModel
,**** LiveData
,和 Lifecycle
。所有這些部分都有自己的責任,他們共同努力建立一個堅實的架構。讓我們看一下擬議架構的簡化圖,以便更好地理解它。

Android架構
如您所見,我們有三個主要元素,每個元素都有其責任。
- 在
Activity
和Fragment
代表的View
層,不與業務邏輯和複雜的操作處理。它只配置檢視,處理使用者互動,最重要的是,觀察和展示LiveData
從中獲取的元素ViewModel
。 - 的
ViewModel
自動觀察Lifecycle
的檢視的狀態下,維持期間配置更改和其他Android生命週期事件的一致性。檢視還要求從中獲取資料Repository
,這是作為可觀察的提供的LiveData
。重要的是要理解,ViewModel
從不View
直接引用,並且資料的更新總是由LiveData
實體完成。 - 這
Repository
不是一個特殊的Android元件。它是一個簡單的類,沒有任何特定的實現,它負責從所有可用的源,從資料庫到Web服務獲取資料。它處理所有這些資料,通常將它們轉換為可觀察資料LiveData
並使它們可用於ViewModel
。 - 該
Room
資料庫是一個SQLite對映庫,它有助於處理資料庫。它會自動編寫大量樣板檔案,在編譯時檢查錯誤,最重要的是,它可以直接返回帶有observable的查詢LiveData
。
我相信你已經注意到我們已經談了很多關於可觀測量的東西。該 Observer模式 是的基地之一 LiveData
元素和 Lifecycle
感知元件。此模式允許物件通知觀察者列表其狀態或資料的任何更改。因此,當一個Activity觀察一個 LiveData
實體時,它會在該資料經過任何修改時收到更新。
另一個Android建議是使用 依賴注入 系統來鞏固其架構,例如Google的 Dagger 2 或使用 服務定位器 模式(這比DI更簡單,但沒有很多優點)。我們不會在本教程中介紹DI或服務定位器,但Envato Tuts +有一些關於這些主題的優秀教程。但是,請注意,使用Dagger 2和Android元件有一些特殊性,將在本系列的第二部分進行說明。
3.架構元件
我們必須深入研究新元件的各個方面,以便能夠真正理解和採用這種架構模型。但是,我們不會深入瞭解本教程中的所有細節。由於每個元素的複雜性,在本教程中,我們只討論每個元素背後的一般概念,並檢視一些簡化的程式碼片段。我們將嘗試覆蓋足夠的空間來展示元件並讓您入門。但不要害怕,因為本系列中的未來文章將深入挖掘並涵蓋架構元件的所有特性。
生命週期感知元件
大多數Android應用程式元件都附加了生命週期,這些生命週期由系統本身直接管理。直到最近,開發人員才能監控元件的狀態並採取相應的措施,在適當的時候初始化和結束任務。然而,很容易混淆並犯這種型別的操作相關的錯誤。但是這個 [android.arch.lifecycle](https://developer.android.com/reference/android/arch/lifecycle/package-summary.html)
包改變了這一切。
現在,活動和片段有一個 [Lifecycle](https://developer.android.com/reference/android/arch/lifecycle/Lifecycle.html)
附加到它們的物件,可以通過 [LifecycleObserver](https://developer.android.com/reference/android/arch/lifecycle/LifecycleObserver.html)
類來觀察,比如 [ViewModel](https://developer.android.com/reference/android/arch/lifecycle/ViewModel.html)
實現此介面的任何物件。這意味著觀察者將收到有關其正在觀察的物件的狀態更改的更新,例如暫停活動或何時啟動。它還可以檢查被觀察物件的當前狀態。因此,現在處理必須考慮框架生命週期的操作要容易得多。

LifecycleObserver對LifecycleEvents做出反應
現在,建立一個 Activity
或 Fragment
符合這一新標準,你要擴充套件 LifecycleActivity
或 LifecycleFragment
。但是,這可能並不總是必要的,因為Android團隊的目標是將這些新工具與其框架完全整合。
class MainActivity : LifecycleActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } }
的LifecycleObserver接收Lifecycle事件,並且可以通過註解反應。不需要方法覆蓋。
class MainActivityObserver : LifecycleObserver, AnkoLogger { @OnLifecycleEvent(Lifecycle.Event.ON_RESUME) fun onResume() { info("onResume") } @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE) fun onPause() { info("onPause") }
該 LiveData
元件
該 LiveData
元件是一個數據持有者,包含可以觀察到的值。鑑於觀察者 Lifecycle
在 LiveData
例項化期間提供了一個, LiveData
將根據 Lifecycle
狀態行事。如果觀察者的 Lifecycle
狀態是 STARTED
或者 RESUMED
,觀察者是 active
; 否則就是 inactive
。
LiveData
知道資料何時被更改,以及觀察者是否 active
應該接收更新。另一個有趣的特性 LiveData
是它能夠在觀察者處於某種 Lifecycle.State.DESTROYED
狀態時將其移除,從而避免在活動和碎片觀察時發生記憶體洩漏。

LiveData值更新過程
一個 LiveData
必須實現 onActive
和 onInactive
方法。
class LocationLiveData(context: Context) : LiveData<Location>(), AnkoLogger, LocationListener { private val locationManager: LocationManager = context.getSystemService(Context.LOCATION_SERVICE) as LocationManager override fun onActive() { info("onActive") locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0f, this) } override fun onInactive() { info("onInactive") locationManager.removeUpdates(this) } // .... }
要觀察LiveData 元件,您必須致電observer(LifecycleOwner, Observer<T>)。
class MainActivity : LifecycleActivity(), AnkoLogger { fun observeLocation() { val location = LocationLiveData(this) location.observe(this, Observer { location -> info("location: $location") }) } }
該 ViewModel
元件
新架構元件中最重要的一類是 ViewModel
,它用於儲存與UI相關的資料,在螢幕輪換等配置更改期間保持其完整性。在 ViewModel
能夠與交談 Repository
,漸漸 LiveData
從它並使它又可以通過檢視來觀察。 ViewModel
也不需要對 Repository
after配置更改進行新呼叫,這會對程式碼進行大量優化。

ViewModel對UI生命週期很緊張
要建立檢視模型,請擴充套件 ViewModel
該類。
class MainActivityViewModel : ViewModel() { private var notes: MutableLiveData<List<String>>? = null fun getNotes(): LiveData<List<String>> { if (notes == null) { notes = MutableLiveData<List<String>>() loadNotes() } return notes!! } private fun loadNotes() { // do async operation to fetch notes } }
要從檢視訪問,您可以致電ViewProviders.of(Activity|Fragment).get(ViewModel::class)。此工廠方法將根據需要返回該例項ViewModel或獲取保留的例項。
class MainActivity : LifecycleActivity(), AnkoLogger { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) val viewModel = ViewModelProviders.of(this) .get(MainActivityViewModel::class.java) viewModel.getNotes().observe( this, Observer { notes -> info("notes: $notes") } ) } }
該 Room
元件
Android從一開始就支援SQLite; 然而,為了使它工作,總是需要寫很多樣板。此外,SQLite沒有儲存POJO(普通舊Java物件),也沒有在編譯時檢查查詢。一路來 Room
解決這些問題!它是一個SQLite對映庫,能夠持久化Java POJO,直接將查詢轉換為物件,在編譯時檢查錯誤,並 LiveData
從查詢結果中生成可觀察物件 。 Room
是一個 物件關係對映 庫,帶有一些很酷的Android附加功能。
到目前為止,您可以完成大部分 Room
能夠使用其他ORM Android庫的功能。但是,它們都沒有得到官方支援,最重要的是,它們無法產生 LifeData
結果。該 Room
庫非常適合作為擬議Android架構上的持久層。
要建立 Room
資料庫,您需要一個 @Entity
持久化,可以是任何Java POJO,一個 @Dao
用於進行查詢和輸入/輸出操作的介面,以及一個 @Database
必須擴充套件的抽象類 RoomDatabase
。
@Entity class Note { @PrimaryKey var id: Long? = null var text: String? = null var date: Long? = null }
@Dao interface NoteDAO { @Insert( onConflict = OnConflictStrategy.REPLACE ) fun insertNote(note: Note): Long @Update( onConflict = OnConflictStrategy.REPLACE ) fun updateNote(note: Note): Int @Delete fun deleteNote(note: Note): Int @Query("SELECT * FROM note") fun findAllNotes(): LiveData<Note> // on Kotlin the query arguments are renamed // to arg[N], being N the argument number. // on Java the arguments assume its original name @Query("SELECT * FROM note WHERE id = :arg0") fun findNoteById(id: Long): LiveData<Note> }
@Database( entities = arrayOf(Note::class), version = 1) abstract class Databse : RoomDatabase() { abstract fun noteDAO(): NoteDAO }
將架構元件新增到專案中
目前,要使用新的架構元件,您需要先將Google儲存庫新增到您的 build.gradle
檔案中。有關更多詳細資訊,請參閱 官方指南 。
allprojects {` `repositories {` `jcenter()` `// Add Google repository` `maven { url '[https://maven.google.com](https://maven.google.com/)' }` `}` `}`
結論
如您所見,Android提出的標準化架構涉及很多概念。不要期望對這個主題有一個完整的瞭解。畢竟,我們只是介紹主題。但是你現在已經掌握了足夠的知識來理解架構背後的邏輯以及不同架構元件的角色。
我們討論了與提議的Android架構及其元件相關的大多數主題; 但是,Repository第一部分不能涵蓋有關元件實現和一些額外內容的詳細資訊,例如類和Dagger 2系統。我們將在下一篇文章中探討這些主題。
再見!
想學習更多Android知識,或者獲取相關資料請加入Android技術開發交流2群:935654177。本群可免費獲取Gradle,RxJava,小程式,Hybrid,移動架構,NDK,React Native,效能優化等技術教程!