1. 程式人生 > >帶你領略Android Jetpack元件的魅力

帶你領略Android Jetpack元件的魅力

1、前言

最近簡單看了下google推出的框架Jetpack,感覺此框架的內容可以對平時的開發有很大的幫助,也可以解決很多開發中的問題,對程式碼的邏輯和UI介面實現深層解耦,打造資料驅動型UI介面。

Android Architecture元件是Android Jetpack的一部分,它們是一組庫,旨在幫助開發者設計健壯、可測試和可維護的應用程式,包含一下元件:

本文是在以上文章完成的基礎上,針對每個元件的使用所做的一點思考,個人感覺所有的開發者都應該儘早的熟悉Jetpack元件,相信一定會被它的魅力所吸引,最近也在完成一個使用以上所有元件實現的專案,作為對Jetpack元件的專案實踐,後面的文章也會推出,下面按照一個專案的構成來分析一下每個元件對專案開發的幫助

2、Android Jetpack

對於任何一個產品來說,我們開發中都會面對哪些問題?如:產品互動、使用者體驗、程式碼結構、資料獲取、資料儲存、網路優化、任務排程等等,雖然在現在的階段這些問題已經有了很好的解決和優化,也有很多大神的開源元件方便開發者去使用,Android Jetpack就是Google給出的一個官方的處理方法(當然知識處理其中基本問題),Android Jetpack元件的優勢:

  1. 輕鬆管理應用程式的生命週期
  2. 構建可觀察的資料物件,以便在基礎資料庫更改時通知檢視
  3. 儲存在應用程式輪換中未銷燬的UI相關資料,在介面重建後恢復資料
  4. 輕鬆的實現SQLite資料庫
  5. 系統自動排程後臺任務的執行,優化使用效能

Android Jetpack元件推薦的使用專案架構

上面架構元件的功能如下:

  1. Activity和Fragment負責產品與使用者的互動
  2. ViewModel作為資料的儲存和驅動
  3. Resposity負責排程資料的獲取
  4. Room儲存本地序列化的資料
  5. Retrofit獲取遠端資料的資料

按照谷歌推薦的專案架構配合Android Jatpack元件的使用,將會有不一樣的開發體驗,下面分析每個元件如何幫我們處理這些問題的。

3、Android Jetpack元件介紹

應用程式的開發和產品與使用者的互動都是從UI開始的,使用者可見的和開發者操作的結果都顯示在介面上,所以介面的操作在卡法中佔據很重要的地位,也是影響我們開發和使用體驗的重要部分,常見的問題如:UI的宣告週期處理、資料的顯示和重新整理、註冊監聽的釋放等, Jetpack架構元件就可以幫我們規範化的解決他們。

  • Lifecycler

Lifecycler是一個生命週期感知元件,執行操作以響應另一個元件(例如活動和片段)的生命週期狀態的更改,簡單來說它可以監聽活動元件宣告週期的變化,在每個宣告週期執行相應的方法,不同於以往想在生命週期中執行相應的方法需要設定介面,然後在宣告週期中回撥介面,這樣會造成程式碼的耦合,也會引發宣告週期的問題;

Lifecycler的優點

  1. Lifecycler實現了執行的邏輯和活動的分離,程式碼解耦並且增加了程式碼的可讀性
  2. Lifecycler在活動結束時自定移除監聽,避免了生命週期的問題

Lifecycler的實現主要使用兩個主要列舉來跟蹤其關聯元件的生命週期狀態

  1. Event:從框架和Lifecycle類派發的生命週期事件。 這些事件對映到活動和片段中的回撥事件。
  2. State:由Lifecycle物件跟蹤的元件的當前狀態。

Lifecycler的原理

Lifecycler為每個活動元件添加了一個沒有介面的Fragment,利用Fragment週期會根據活動宣告週期變化的特性實現的特性,從而實現生命週期的感知,然後根據註解的Event查詢執行相應的方法。

關於Lifecycler的使用和原始碼請檢視一下兩篇文章:

  • LiveData

在產品的開發中我們都有必須的操作就是資料的更新,當用戶執行某種操作或伺服器資料發生改變後,都要重新獲取資料再次重新整理介面的UI,每改變一次就要重複一次,從程式碼封裝的角度,有沒有一種工具可以監聽資料狀態,在資料變化的時候自動更新UI呢?LiveData就提供了此項更能,從名字中可以看出這個Data時Live的,不是一個死資料,解決了資料展示和重新整理的問題

LiveData重新整理的使用:

  1. 只需建立LiveData例項後,為可觀察的資料新增觀察者,在資料改變時會自動回撥觀察者
//建立觀察者物件
val nameObservable = Observer<String> {   // 建立觀察者物件
    textView.text = it       // 定義onChange()方法中的操作
}

LiveData的幾點注意事項:

  1. 是一個具有宣告週期感知特性的可觀察的資料保持類,使用LiveData儲存資料時,在每次訂閱或資料更新時會自動回撥設定的觀察者從而更新資料,真正的實現了資料驅動的效果
  2. LiveData 認為觀察者的生命週期處於STARTED狀態或RESUMED狀態下,表示觀察者處於活動狀態,LiveData只通知活躍的觀察者去更新資料
  3. LiveData會在活動處於Destroy時釋放觀察者,所以開發者無需特別處理

LiveData原理:

內部儲存了LifecycleOwner和Observer,利用LifecycleOwner感知並處理宣告中期的變化,Observer在資料改變時遍歷所有觀察者並回調方法

  • ViewModel

如果你認為上面的方法只是對程式的開發有一點優化的話,那ViewModel的出現確實解決一個簡單而又繁瑣的問題,大家都知道使用者在使用產品的過程中,可能隨時會被中斷或介面發生重建,如果資料的丟失會造成很差的使用者體驗,當然現在都知道在onSaveInstanceState()中儲存資料,在介面重建時恢復資料,這種雖然可以解決問題,但會造成每個介面都要編寫板寸和恢復的程式碼,而且資料量過大時會影響執行效能,VIewModel的出現就是解決這個問題,它會在活動重建時仍然儲存資料,在活動建立完成後從中獲取資料

ViewModel的生命週期:

  1. ViewModel物件的範圍是在獲取ViewModel時傳遞給ViewModelProvider的Lifecycle生命週期
  2. ViewModel在記憶體中直到Activity銷燬或Fragment被移除
  3. 系統首次呼叫活動物件的onCreate()方法時,通常會請求ViewModel
  4. 系統可能會在整個活動的整個生命週期中多次呼叫onCreate(),例如當裝置螢幕旋轉時
  5. ViewModel從第一次請求ViewModel直到活動完成並銷燬時存在

ViewModel的優點:

  1. 資料和介面的分離,使資料驅動介面
  2. 解決了執行中斷和介面重建時的資料儲存問題
  3. 配合LiveData實時獲取最新資料
  4. 實現Activity中Fragment之間的資料互動

ViewModel原理:

將資料儲存到ViewModel中,然後為活動中新增一個HolderFragment,HolderFragment中儲存了ViewStore的例項,ViewStore中使用Map儲存了ViewModel,從而在活動重新建立時獲取到原來的ViewModel

注:一般時VIewModel和LiveData組合儲存可觀察的資料

  • Paging

RecyclerView是專案中展示資料所必不可少的控制元件,伴隨者列表展示而來的就是下拉載入,目前有很多開源的框架已支援下拉載入,主要分兩種:

  1. 當滑動到最後一個Item時,觸發載入更多的資料,此時使用者會看到載入過程並等待載入完成
  2. 根據顯示的position,在未到最後之前就去載入資料並重新整理介面,這樣使用者可以流暢的滑動下去

Paging的實現和上述原理相似,效果與第二種一致,可以更輕鬆地在應用程式RecycleView中逐步和優雅地載入資料,看下Paging的實現:

上述組成部分的作用:

  1. DataSource:資料的來源,需要設定初始化和載入更多的邏輯以及每次載入變化的Key
  2. PagedList:資料集散中心;根據需要向DataSource索取載入資料,並將得到的資料傳遞到PagedListAdapter
  3. PagedListAdapter:資料介面卡,這裡處了起到普通介面載入介面卡的作用外,更重要的是根據滑動顯示的座標,起到了確定什麼時候要求向PagedList載入資料
  4. DiffUtil.ItemCallback:判斷資料是否發生改變以相應介面的更新

Paging的好處

  1. 輕鬆流暢的實現下拉載入
  2. 使用LiveData<PagedList>實現資料的可觀察
  3. 配合Room實現資料庫的載入和監聽
  4. 支援自定義DataSource

Paging實現的原理:

簡單來說就是在PageListAdapter中顯示資料,然後根據顯示的position確定是否需要載入資料,當觸發載入資料時,PagedList呼叫DataSource中配置的方法載入資料,並將資料傳遞到Adapter重新整理UI

  • Room

資料庫在專案開發中起著至關重要的作用,所有的操作都在修改著資料,而資料的修改驅動UI更新,從而行成了產品的互動;在開發中如果使用Android原生的SQLite資料庫,需要編寫大量的樣板程式碼,而Room元件可以讓你使用幾個註解,就可以省略大量的程式碼,同時支援更強大的資料庫訪問;

Room提供了三個主要的元件:

  1. @Database:用來註解類,並且註解的類必須是繼承自RoomDatabase的抽象類。該類主要作用是建立資料庫和建立Dao
  2. @Entity:用來註解實體類,@Database通過entities屬性引用被@Entity註解的類,並利用該類的所有欄位作為表的列名來建立表。
  3. @Dao:用來註解一個介面或者抽象方法,該類的作用是提供訪問資料庫的方法。在使用@Database註解的類中必須定一個不帶引數的方法,這個方法返回使用@Dao註解的類

Room使用的優點:

  1. 樣板程式碼通過註解自動生成,提高開發效率
  2. 可以返回可觀察的資料,在資料庫改變時自動更新
  3. 可以配合Paging使用實現下拉載入
  4. 支援Cursor和Observable查詢

Room的實現原理:

Room的實現原理其實是很多框架的實現方式,是一種程式碼註解,在編譯時自動生成的方式(Java註解程式碼生成);如:ButterKnife框架。

  • Navigation

Navigation框架是Jetpack框架中新的元件,也是比較有意思的和創新的框架,它將程式中介面導航像layout檔案一樣可視化了,在xml中直接可以編輯和修改介面的導航,簡化了應用中目標之間導航的實現,如:

在naviagtion.xml檔案的design中新增元素並設定導航,下xml中就會自動填充程式碼:

<navigation xmlns:android="http://schemas.android.com/apk/res/android"
            xmlns:app="http://schemas.android.com/apk/res-auto"
            xmlns:tools="http://schemas.android.com/tools"
            android:id="@+id/navigation"
            app:startDestination="@id/blankFragment">
        <fragment  ....../>
 
        <fragment 
           android:id="@+id/blankFragment" 
           android:name="com.example.administrator.navigation.BlankFragment"
        <action
           android:id="@+id/action_otherFragment_to_blankFragment"// 在導航時呼叫此ID設定目的
           app:destination="@id/blankFragment" />
        </fragment>
</navigation>

呼叫新增的action即可跳轉介面實現導航

btnFragment.setOnClickListener {
    Navigation.findNavController(btnFragment).navigate(R.id.action_blankFragment_to_secondFragment)
}

Navigation的優點:

  1. 專案介面導航視覺化
  2. 簡化介面導航的實現過程
  • WorkManger

WorkManger是Android Jetpack提供執行後臺任務管理的元件,它適用於需要保證系統即使應用程式退出也會執行的任務,可以根據需求設定執行任務的條件,如:插入電源、空閒狀態

  1. 如果程式處於執行狀態,WorkManager可以在您應用程式程序的新執行緒中執行您的任務
  2. 如果程式未執行,WorkManager會選擇一種合適的方式來安排後臺任務 ,可能會使用 JobScheduler,Firebase JobDispatcher或AlarmManager
  3. 所有的操作都有WokManger排程,開發者無需編寫其他排程處理

WorkManager的組成:

  1. Worker:指定需要執行的任務,可以繼承抽象的Worker類,在實現的方法中編寫執行的邏輯
  2. WorkRequest:建立任務請求(執行一項單一任務)
  3. WorkManager:排隊和管理工作請求
  4. WorkStatus:包含有關特定任務的資訊
  5. Constraints:指定對任務執行時間的限制(任務約束)

WorkManager的基本使用:

  1. 定義Worker的實現類
class TestWorker(context: Context, workerParameters: WorkerParameters) : Worker(context, workerParameters) {

    override fun doWork(): Result {
        Log.e("TestWorker", "執行了 doWork() 操作!")
        return Result.SUCCESS
    }
}
  1. 建立workRequest請求
val workRequest = OneTimeWorkRequest.Builder(TestWorker::class.java).build()
  1. 使用WorkManger執行請求
WorkManager.getInstance().enqueue(workRequest)

好了,Android Jetpack元件介紹完畢了,開篇時還是十一之前,前前後後拖了好久!本篇是開篇也是入門介紹篇,但確實是在分析和使用了所有元件之後做的一點介紹和總結,當你把Jetpack所有元件聯合使用時,你就會發現不一樣的妙處,元件之間的聯絡產生了化學反應,使得整個專案的架構和邏輯清晰明瞭,專案的執行也變得更加穩定,希望這幾篇的學習能對所有想使用Jetpack元件的同學有所幫助!