Jetpack系列全解析

一、什么是Jetpack?

Jetpack并不是一個框架或者組件,它是一套庫辜梳、工具和指南的集合,可幫助開發(fā)者更輕松地編寫優(yōu)質(zhì)應(yīng)用泳叠。這些組件可幫助開發(fā)者遵循最佳做法作瞄、擺脫編寫樣板代碼的工作并簡化復(fù)雜任務(wù),以便將精力集中放在所需的代碼上危纫。
Android Jetpack中的很多組件并不都是新開發(fā)的宗挥,而是很早就有了,比如在Goole I/O 2017大會時推出了 Android Architecture Component(AAC)种蝶,它包括了LifeCycle契耿、LiveData、ViewModel蛤吓、Room宵喂。在Goole I/O 2018大會上,
用AndroidX替代了Android Support Library会傲,并在Android Architecture Component的基礎(chǔ)上發(fā)布了Android Jetpack锅棕,AndroidX也是屬于Android Jetpack拙泽。

Jetpack主要特性有以下三點:

1.加速開發(fā)
組件可單獨使用,也可以協(xié)同工作裸燎,當(dāng)使用kotlin語言特性時顾瞻,可以提高效率。
2.消除樣板代碼
Android Jetpack可管理繁瑣的Activity(如后臺任務(wù)德绿、導(dǎo)航和生命周期管理)荷荤。
3.構(gòu)建高質(zhì)量的強大應(yīng)用
Android Jetpack組件圍繞現(xiàn)代化設(shè)計實踐構(gòu)建而成,具有向后兼容性移稳,可以減少崩潰和內(nèi)存泄漏蕴纳。

二、Android Jetpack架構(gòu)組件 Lifecycle

2.1 什么是Lifecycle

Lifecycle用于幫助開發(fā)者管理Activity和Fragment 的生命周期

2.2 Lifecycle基本用法
先不談Activity和Fragment中如何使用个粱,先舉一個Lifecycle的簡單例子古毛。

public class MyObserver implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    public void connectListener() {
        ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void disconnectListener() {
        ...
    }
}
myLifecycleOwner.getLifecycle().addObserver(new MyObserver());//1

復(fù)制代碼新建一個MyObserver類,它實現(xiàn)了LifecycleObserver接口都许,說明MyObserver成為了一個Lifecycle的觀察者稻薇。
然后在注釋1處將MyObserver添加到LifecycleOwner中。LifecycleOwner是一個接口胶征,其內(nèi)部只有一個方法getLifecycle()塞椎,getLifecycle方法用于獲取Lifecycle,這樣就可以將MyObserver添加到Lifecycle中睛低,當(dāng)Lifecycle的生命周期發(fā)生變化時案狠,MyObserver就會觀察到,或者說是感知到钱雷。
如果使用是Java8 ,那么可以使用DefaultLifecycleObserver來替代LifecycleObserver:

class MyObserver implements DefaultLifecycleObserver {
     @Override
     public void onCreate(LifecycleOwner owner) {
         ...
     }
 }

復(fù)制代碼除此之外莺戒,不要忘了在build.gradle添加 "androidx.lifecycle:common-java8:<version>"

2.3.Lifecycle應(yīng)用舉例

應(yīng)用舉例準備兩個示例,在Activity中使用

package com.example.lifecycledemo1;

import android.arch.lifecycle.Lifecycle;
import android.arch.lifecycle.LifecycleObserver;
import android.arch.lifecycle.OnLifecycleEvent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getLifecycle().addObserver(new MyObserver());//1
    }

    public class MyObserver implements LifecycleObserver{

        @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
        void onResume(){
            Log.d(TAG, "Lifecycle call onResume");
        }
        @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
        void onPause(){
            Log.d(TAG, "Lifecycle call onPause");
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "onResume");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.d(TAG, "onPause");

    }
}

復(fù)制代碼先實現(xiàn)MyObserver急波,對ON_CREATE和ON_RESUME事件進行監(jiān)聽从铲。因為在Android Support Library 26.1.0 及其之后的版本,Activity和Fragment已經(jīng)默認實現(xiàn)了LifecycleOwner接口澄暮,所以在注釋1處可以直接使用getLifecycle方法獲取Lifecycle對象名段,這樣MyObserver就可以觀察MainActivity的生命周期變化了,LifecycleOwner可以理解為被觀察者泣懊,MainActivity默認實現(xiàn)了LifecycleOwner接口伸辟,也就是說MainActivity是被觀察者。
運行程序馍刮,打印的log如下所示信夫。

D/MainActivity: onResume
D/MainActivity: Lifecycle call onResume
D/MainActivity: Lifecycle call onPause
D/MainActivity: onPause

只要在MainActivity的onCreate方法中添加MyObserver,那么MyObserver就可以觀察到MainActivity的各個生命周期的變化。

三静稻、Android Jetpack架構(gòu)組件 LiveData

3.1 什么是LiveData

LiveData是一個感知數(shù)據(jù)變化的持有者警没,一般是感知Viewmodel的數(shù)據(jù)!

LiveData如同它的名字一樣振湾,是一個可觀察的數(shù)據(jù)持有者杀迹,和常規(guī)的observable不同,LiveData是具有生命周期感知的押搪,這意味著它能夠在Activity树酪、Fragment、Service中正確的處理生命周期大州。
LiveData的數(shù)據(jù)源一般是ViewModel续语,也可以是其它可以更新LiveData的組件。當(dāng)數(shù)據(jù)更新后厦画,LiveData 就會通知它的所有觀察者绵载,比如Activiy。與RxJava的方法不同的是苛白,LiveData并不是通知所有觀察者,它 只會通知處于Active狀態(tài)的觀察者焚虱,如果一個觀察者處于Paused或Destroyed狀態(tài)购裙,它將不會收到通知。
這對于Activiy和Service特別有用鹃栽,因為它們可以安全地觀察LiveData對象而不用擔(dān)心內(nèi)存泄漏的問題躏率。開發(fā)者也不需要在onPause或onDestroy方法中解除對LiveData的訂閱。還有一點需要注意的是一旦觀察者重新恢復(fù)Resumed狀態(tài)民鼓,它將會重新收到LiveData的最新數(shù)據(jù)薇芝。

image.png

3.2 LiveData的基本用法
LiveData是一個抽象類,它的最簡單的實現(xiàn)類為MutableLiveData丰嘉,這里舉個最簡單的例子夯到。

public class MainActivity extends AppCompatActivity {
   private static final String TAG="MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MutableLiveData<String> mutableLiveData  = new MutableLiveData<>();
        //觀察者,觀察到數(shù)據(jù)變化顯示出來
        mutableLiveData.observe(this, new Observer<String>() {//1
            @Override
            public void onChanged(@Nullable final String s) {
                Log.d(TAG, "onChanged:"+s);
            }
        });
        //被觀察者數(shù)據(jù)饮亏,異步線程運行
        mutableLiveData.postValue("Android進階三部曲");//2
    }
}

注釋1處的observe方法有兩個參數(shù)分別是LifecycleOwner和 Observer<T> 耍贾,第一個參數(shù)就是MainActivity本身,第二個參數(shù)新建了一個Observer<String>路幸,在onChanged方法中得到回調(diào)荐开。注釋處的postValue方法會在主線程中更新數(shù)據(jù),這樣就會得到打印的結(jié)果简肴。

D/MainActivity: onChanged:Android進階三部曲

在大多數(shù)情況下晃听,LiveData的observe方法會放在onCreate方法中,如果放在onResume方法中,會出現(xiàn)多次調(diào)用的問題能扒。除了MutableLiveData的postValue方法佣渴,還可以使用setValue方法,它們之前的區(qū)別是赫粥,setValue方法必須在主線程使用观话,如果是在工作線程中更新LiveData,則可以使用postValue方法越平。

3.3 LiveData源碼分析


         model.getLiveData().observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable final String newName) {
                //響應(yīng)接受的消息
                tvReceiveData.setText(newName);
            }
        });

           1.這個代碼必須放到主線程频蛔,不然崩潰assertMainThread("observe");

           2.Activity生命周期銷毀了的話直接退出不執(zhí)行,所以不會引發(fā)內(nèi)存泄漏
           if (owner.getLifecycle().getCurrentState() == DESTROYED) {
                  return;
             }

           3.LifecycleBoundObserver裝飾器秦叛,封裝LifecycleOwner晦溪,Observer這兩個對象

           4.owner.getLifecycle().addObserver(wrapper);將觀察者與LifecycleOwner進行綁定

           5.Activity銷毀就取消訂閱,因此不會內(nèi)存泄漏


============================================================================

         model.getLiveData().setValue("我是點擊按鈕發(fā)送的消息");

         1.for循環(huán)遍歷所有的觀察者
         2.調(diào)用觀察者的observer.mObserver.onChanged((T) mData);因此在每個觀察者的onChanged方法可以監(jiān)聽到數(shù)據(jù)變化挣跋。

總結(jié):

1.LiveData 是如何跟 LifecycleOwner 進行綁定三圆,做到感知生命周期的?
答:LifeData 在 observe 方法中用 LifecycleBoundObserver 包裝了 observer 避咆,并且通過它綁定了owner舟肉。

2.LiveData 會自動在 DESTROY 的狀態(tài)下取消訂閱,是怎么處理的查库?
答:LifecycleBoundObserver 在 onStateChanged() 方法里處理了生命周期改變的事件路媚,當(dāng)接收到 DESTROYED 的事件會自動解除跟 owner 的綁定。

生命周期變化后數(shù)據(jù)處理流程是怎么樣的樊销?

LiveData 的實現(xiàn)基于觀察者模式整慎;
LiveData 跟 LifecycleOwner 綁定,能感知生命周期變化围苫,并且只會在 LifecycleOwner 處于 Active 狀態(tài)(STARTED/RESUMED)下通知數(shù)據(jù)改變裤园;如果數(shù)據(jù)改變發(fā)生在非 active 狀態(tài),數(shù)據(jù)會變化剂府,但是不發(fā)送通知拧揽,等 owner 回到 active 的狀態(tài)下,再發(fā)送通知腺占;
LiveData 會自動在 DESTROYED 的狀態(tài)下移除 Observer 强法,取消訂閱,所以不用擔(dān)心內(nèi)存泄露湾笛;
在 LifecycleOwner 處于 DESTROYED 的狀態(tài)下饮怯,不能訂閱;
postValue 方法其實最后調(diào)用了 setValue 只不過把操作放到主線程嚎研,適合在異步線程里調(diào)用蓖墅,setValue 必須在主線程里調(diào)用库倘;
如果同時多次調(diào)用 postValue 或 setValue 修改數(shù)據(jù),只會修改成最新的那個數(shù)據(jù)论矾,也即只會收到一次通知(set post混合調(diào)用則不一定)教翩;
如果 LiveData 有數(shù)據(jù),并且 owner 在 active 狀態(tài)下贪壳,那么在訂閱的時候饱亿,會立馬收到一次通知;
一個 Observer 實例闰靴,只能綁定一個 LifecycleOwner彪笼,而一個 owner 可以綁定多個 Observer 實例;
LiveData 利用版本管理蚂且、綁定 Lifecycle 確保了只會發(fā)送最新的數(shù)據(jù)給 active 狀態(tài)下的 Observer配猫;

LiveData 基于觀察者模式,并且可以感知生命周期杏死,這使得我們使用 LiveData 既可以享受觀察者模式帶來的隔離數(shù)據(jù)與 UI 等強大的解耦能力泵肄,還可以享受感知生命周期帶來的巨大便利。并且還無需擔(dān)心內(nèi)存泄露這個令人頭疼的問題淑翼。

四腐巢、Android Jetpack架構(gòu)組件 ViewModel

4.1.什么是ViewModel

ViewModel,感知生命周期的形式來存儲和管理視圖相關(guān)的數(shù)據(jù)玄括。針對數(shù)據(jù)冯丙。

在說ViewModel前,我們需要解一下MVVM和DataBinding.MVVM最早于2005年被微軟的架構(gòu)師John Gossman提出惠豺,在2015年Google I/O大會上發(fā)布了MVVM的支持庫DataBinding,DataBinding遭到了一些開發(fā)者的詬病风宁,主要是綁定數(shù)據(jù)時如果出現(xiàn)問題會很難排查洁墙,這樣就沒有一個合適的ViewModel規(guī)范來幫助開發(fā)者來實現(xiàn)MVVM。
在2017年的Google I/O大會上戒财,谷歌推出了ViewModel組件热监,來規(guī)范化ViewModel層。
ViewModel顧名思義饮寞,是以感知生命周期的形式來存儲和管理視圖相關(guān)的數(shù)據(jù)孝扛。ViewModel主要有以下的特點:
1.當(dāng)Activity被銷毀時,我們可以使用onSaveInstanceState()方法恢復(fù)其數(shù)據(jù)幽崩,這種方法僅適用于恢復(fù)少量的支持序列化苦始、反序列化的數(shù)據(jù),不適用于大量數(shù)據(jù)慌申,如用戶列表或位圖陌选。而ViewModel不僅支持大量數(shù)據(jù),還不需要序列化、反序列化操作咨油。
2.Activity/Fragment(視圖控制器)主要用于顯示視圖數(shù)據(jù)您炉,如果它們也負責(zé)數(shù)據(jù)庫或者網(wǎng)絡(luò)加載數(shù)據(jù)等操作,那么一旦邏輯過多役电,會導(dǎo)致視圖控制器臃腫赚爵,ViewModel可以更容易,更有效的將視圖數(shù)據(jù)相關(guān)邏輯和視圖控制器分離開來法瑟。
3.視圖控制器經(jīng)常需要一些時間才可能返回的異步調(diào)用冀膝,視圖控制器需要管理這些調(diào)用,在合適的時候清理它們瓢谢,以確保它們的生命周期不會大于自身畸写,避免內(nèi)存泄漏。而ViewModel恰恰可以避免內(nèi)存泄漏的發(fā)生氓扛。

4.2.ViewModel基本使用
自定義ViewModel繼承ViewMode枯芬,實現(xiàn)自定義ViewModel。

import android.arch.lifecycle.LiveData;
import android.arch.lifecycle.MutableLiveData;
import android.arch.lifecycle.ViewModel;

public class MyViewModel extends ViewModel {
    private MutableLiveData<String> name;
    public LiveData<String> getName() {
        if (name == null) {
            name = new MutableLiveData<String>();
            addName();
        }
        return name;
    }
    private void addName() {
        name.setValue("Android進階解密");
    }
}

getName方法中創(chuàng)建一個MutableLiveData采郎,并通過MutableLiveData的setValue方法來更新數(shù)據(jù)千所。
使用ViewModel然后就可以在Activity中使用MyViewModel了,如下所示蒜埋。

import android.arch.lifecycle.Observer;
import android.arch.lifecycle.ViewModelProviders;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);
        model.getName().observe(this, new Observer<String>() {
            @Override
            public void onChanged(@Nullable String s) {
                   Log.d(TAG, "暢銷書:"+s);
            }
        });
    }
}

通過ViewModelProviders就可以獲得MyViewModel的實例淫痰,然后配合LiveData就可以觀察Name的變化。打印結(jié)果為:

D/MainActivity: 書名為Android進階解密

4.3.ViewModel的生命周期

在旋轉(zhuǎn)設(shè)備屏幕時整份,Activity會被銷毀重新創(chuàng)建待错,而ViewModel卻不會這樣,它的生命周期如下所示烈评。


image.png

可以看到火俄,Activity的生命周期不斷變化,經(jīng)歷了被銷毀重新創(chuàng)建讲冠,而ViewModel的生命周期沒有發(fā)生變化瓜客。

4.4 ViewModel源碼解析

        MyViewModel model = ViewModelProviders.of(this).get(MyViewModel.class);

          1.ViewModel是怎么創(chuàng)建的?   
               get方法里面反射實例化ViewModel
          2.ViewModel是怎么存儲的竿开?  
                 ViewModelStore mViewModelStore;
                  ViewModelStore 結(jié)構(gòu):HashMap<String, ViewModel> 
                  mViewModelStore.put(key, viewModel);
          3.ViewModel為什么可以實現(xiàn)屏幕旋轉(zhuǎn)不丟失數(shù)據(jù)谱仪?   屏幕狀態(tài)發(fā)生改變會拿到上一次屏幕旋轉(zhuǎn)的值

        NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
        ViewModelStore mViewModelStore = nc.viewModelStore;
        每次拿到上次屏幕旋轉(zhuǎn)的ViewModelStore ,從而拿到ViewModel 

參考資料:
Android Jetpack架構(gòu)組件(一)帶你了解Android Jetpack
https://juejin.cn/post/6844903976815558663

Android Jetpack架構(gòu)組件(二)一文帶你了解Lifecycle(使用篇)
https://juejin.cn/post/6844903977788801032

Android Jetpack架構(gòu)組件(三)一文帶你了解Lifecycle(原理篇)
https://juejin.cn/post/6844903977788817416

Android Jetpack架構(gòu)組件(四)一文帶你了解LiveData(使用篇)
https://juejin.cn/post/6844903982691794957

Android Jetpack架構(gòu)組件(五)一文帶你了解LiveData(原理篇)
https://juejin.cn/post/6844903982691794952

Android Jetpack架構(gòu)組件(六)一文帶你了解ViewModel的使用和原理
https://juejin.cn/post/6844903983471935495

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子末秃,更是在濱河造成了極大的恐慌,老刑警劉巖卸例,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件称杨,死亡現(xiàn)場離奇詭異,居然都是意外死亡筷转,警方通過查閱死者的電腦和手機姑原,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來呜舒,“玉大人锭汛,你說我怎么就攤上這事∠龋” “怎么了唤殴?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長到腥。 經(jīng)常有香客問我朵逝,道長,這世上最難降的妖魔是什么乡范? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任配名,我火速辦了婚禮,結(jié)果婚禮上晋辆,老公的妹妹穿的比我還像新娘渠脉。我一直安慰自己,他們只是感情好瓶佳,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布芋膘。 她就那樣靜靜地躺著,像睡著了一般霸饲。 火紅的嫁衣襯著肌膚如雪为朋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天厚脉,我揣著相機與錄音习寸,去河邊找鬼。 笑死器仗,一個胖子當(dāng)著我的面吹牛融涣,可吹牛的內(nèi)容都是我干的童番。 我是一名探鬼主播精钮,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼剃斧!你這毒婦竟也來了轨香?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤幼东,失蹤者是張志新(化名)和其女友劉穎臂容,沒想到半個月后科雳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡脓杉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年糟秘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片球散。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡尿赚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蕉堰,到底是詐尸還是另有隱情凌净,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布屋讶,位于F島的核電站冰寻,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏皿渗。R本人自食惡果不足惜斩芭,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望羹奉。 院中可真熱鬧秒旋,春花似錦、人聲如沸诀拭。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽耕挨。三九已至细卧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間筒占,已是汗流浹背贪庙。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留翰苫,地道東北人止邮。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像奏窑,于是被迫代替她去往敵國和親导披。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容