Android官方架構(gòu)組件介紹之LifeCycle

Google 2017 I/O開發(fā)者大會于近日召開,在開發(fā)者大會上谷歌除了發(fā)布了Android O等一些新產(chǎn)品之外葱蝗,也對Android代碼的架構(gòu)做出了一個官方的回應(yīng)立磁。

Google 2017 I/O開發(fā)者大會Android架構(gòu)組件介紹現(xiàn)場視頻

下面是官方提供的Android App開發(fā)的架構(gòu)圖:

google官方Android架構(gòu)圖

從上圖可以看到一些關(guān)鍵字:ViewModel,LiveData,Room等颂翼。其實看了上面視頻的會發(fā)現(xiàn)Google官方Android架構(gòu)組件一共包括以下幾個:

  • LifeCycle : 與Activity和Fragment的生命周期有關(guān)
  • LiveData :異步可訂閱數(shù)據(jù)晃洒,也是生命周期感知
  • ViewModel :視圖數(shù)據(jù)持有模型,也是生命周期感知
  • Room :SQLite抽象層朦乏,用于簡化SQLite數(shù)據(jù)存儲

這篇文章主要講解LifeCycle在項目的簡單用法球及。

AS中添加依賴

首先在工程根目錄的build.gradle中添加一下內(nèi)容:

allprojects {
    repositories {
        jcenter()
        maven { url 'https://maven.google.com' }  //添加此行
    }
}

然后在應(yīng)用目錄下的build.gradle中添加以下依賴:

//For Lifecycles, LiveData, and ViewModel
compile "android.arch.lifecycle:runtime:1.0.0-alpha1"
compile "android.arch.lifecycle:extensions:1.0.0-alpha1"
annotationProcessor "android.arch.lifecycle:compiler:1.0.0-alpha1"

//For Room
compile "android.arch.persistence.room:runtime:1.0.0-alpha1"
annotationProcessor "android.arch.persistence.room:compiler:1.0.0-alpha1"

LifeCycle相關(guān)使用

在我們平時的項目中經(jīng)常會遇到很多需要依賴生命周期的邏輯處理,比如有這么一個需求呻疹。
在某個Activity我們需要在屏幕上展現(xiàn)用戶的地理位置吃引。簡單的實現(xiàn)方法如下:

class MyLocationListener {
    public MyLocationListener(Context context, Callback callback) {
        // ...
    }

    void start() {
        // connect to system location service
    }

    void stop() {
        // disconnect from system location service
    }
}

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, (location) -> {
            // update UI
        });
  }

    public void onStart() {
        super.onStart();
        myLocationListener.start();
    }

    public void onStop() {
        super.onStop();
        myLocationListener.stop();
    }
}

雖然以上代碼看起來很簡潔,但在實際項目中的onStart,onStop方法可能會變得相當(dāng)龐大镊尺。
此外朦佩,實際情況可能并不像上面這么簡單,例如我們需要在start位置監(jiān)聽前做用戶狀態(tài)檢測庐氮,檢測是一個耗時的任務(wù)语稠,那么很有可能在檢測結(jié)束前用戶提前退出了Activity,這時候就會導(dǎo)致myLocationListener.start()myLocationListener.stop()后面調(diào)用弄砍,從而引起很多難以定位的問題仙畦。代碼如下:

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, location -> {
            // update UI
        });
    }

    public void onStart() {
        super.onStart();
        Util.checkUserStatus(result -> {
            // what if this callback is invoked AFTER activity is stopped?
            if (result) {
                myLocationListener.start();
            }
        });
    }

    public void onStop() {
        super.onStop();
        myLocationListener.stop();
    }
}

這時候就該今天的主角LifeCycle出場了。它提供了一套接口幫助你處理這些問題音婶。

LifeCycle

LifeCyle類持有Activity或者Fragment的生命周期相關(guān)信息慨畸,并且支持其他對象監(jiān)聽這些狀態(tài)。

LifeCyle有兩個枚舉用于追蹤生命周期中的狀態(tài)衣式。

Event

這是生命周期的事件類寸士,會在Framework和LifeCycle間傳遞,這些事件映射到Activity和Fragment的回調(diào)事件中碴卧。

State

LifeCycle所持有Activity或Fragment的當(dāng)前狀態(tài)弱卡。

一個類想要監(jiān)聽LifeCycle的狀態(tài),只需要給其方法加上注解:

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

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    public void onPause() {
    }
}
aLifecycleOwner.getLifecycle().addObserver(new MyObserver());

LifeCycleOwner

LifeCycleOwner是一個只有一個方法的接口用于表明其有一個LifeCycle對象螟深。這個方法為getLifecycle()谐宙。
這個對象給Acitivity,F(xiàn)ragment和LifeCycle提供了一個很好的抽象關(guān)系界弧,Activity和Fragment只要實現(xiàn)這個接口就能配合LifeCycle實現(xiàn)生命周期監(jiān)聽。

注意:由于目前LifeCycle處于alpha階段搭综,所以Fragment和AppCompatActivity并不會實現(xiàn)這些方法垢箕,在此之前,可以使用LifecycleActivityLifecycleFragment兑巾。等LifeCycle趨于穩(wěn)定后条获,F(xiàn)ragment和AppCompatActivity會默認(rèn)實現(xiàn)這些。

對于之前的位置監(jiān)聽的例子蒋歌,我們可以讓MyLocationListener繼承LifecycleObserver帅掘,在onCreate中使用LifeCycle進(jìn)行初始化,剩下的問題則不必?fù)?dān)心了堂油。因為MyLocationListener有能力進(jìn)行生命周期的判斷修档。

class MyActivity extends LifecycleActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        //此處進(jìn)行初始化getLifecycle()傳入LifeCycle對象
        myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
            // update UI
        });
        //檢測用戶狀態(tài)并啟用監(jiān)聽
        Util.checkUserStatus(result -> {
            if (result) {
                myLocationListener.enable();
            }
        });
  }
}

下面看一下MyLocationListener

class MyLocationListener implements LifecycleObserver {
    private boolean enabled = false;
    public MyLocationListener(Context context, Lifecycle lifecycle, Callback callback) {
       ...
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    void start() {
        if (enabled) {
           // connect
        }
    }

    public void enable() {
        enabled = true;
        //?
        if (lifecycle.getState().isAtLeast(STARTED)) {
            // connect if not connected
        }
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    void stop() {
        // disconnect if connected
    }
}

LifeCycle最重要的特性就是在?處,他可以提供主動查詢生命周期狀態(tài)的方法府框。這樣就避免了上面遇到的myLocationListener.start()myLocationListener.stop()后面調(diào)用的問題吱窝。

通過以上的實現(xiàn),我們的LocationListener是完全的生命周期感知了,它可以進(jìn)行自己的初始化和資源清理而不必受Activity或者Fragment的管理院峡。這時候如果我們在其他Activity或者Fragment中使用LocationListener兴使,我們只需要初始化它就行了,不必再擔(dān)心生命周期對它的影響照激,因為它內(nèi)部會做好這一切发魄。

通過LefeCycle工作的類我們稱之為生命周期感知。鼓勵需要使用Android生命周期的類的庫提供生命周期感知組件俩垃,以便客戶端可以輕松地在客戶端上集成這些類励幼,而無需手動生命周期管理。

LiveData就是生命周期感知組件的示例吆寨,將LiveData和ViewModel一起使用赏淌,可以在遵循Android生命周期的情況下,更容易的使用數(shù)據(jù)來填充UI啄清。

生命周期的最佳實踐

  • 保持你的UI(Activity和Fragment)盡可能簡潔六水。它們不應(yīng)該試圖獲取它們的數(shù)據(jù)而是使用ViewModel來執(zhí)行此操作,并通過LiveData的回調(diào)將數(shù)據(jù)更新到UI中辣卒。
  • 嘗試編寫數(shù)據(jù)驅(qū)動的UI掷贾,你的UI的責(zé)任是在數(shù)據(jù)更改時更新視圖,或?qū)⒂脩舨僮魍ㄖoViewModel荣茫。
  • 將你的數(shù)據(jù)邏輯放在ViewModel類中想帅。 ViewModel應(yīng)該作為UI和其他數(shù)據(jù)操作的連接器。值得注意的是啡莉,ViewModel并不負(fù)責(zé)提取數(shù)據(jù)(例如港准,從網(wǎng)絡(luò))。相反咧欣,ViewModel應(yīng)該調(diào)用其他接口來執(zhí)行此工作浅缸,然后將結(jié)果提供給UI。
  • 使用Data Binding可以讓你的的UI代碼變得相當(dāng)干凈利落魄咕。這將使你的UI更具聲明性衩椒,并最大限度地減少書寫UI更新的代碼。如果您更喜歡在Java中執(zhí)行此操作哮兰,請使用像Butter Knife這樣的庫來避免使用樣板代碼并進(jìn)行更好的抽象毛萌。
  • 如果你有一個復(fù)雜的UI,請考慮創(chuàng)建一個Presenter類來處理UI修改喝滞。這通常是過度架構(gòu)的阁将,但可能有助于使你的UI更容易測試。
  • 不要在ViewModel中引用View或Activity上下文囤躁。如果ViewModel在Activity或View銷毀的情況下依舊存活冀痕,這時將導(dǎo)致內(nèi)存泄漏荔睹。

補(bǔ)充

在自定義的Activity或Fragment中實現(xiàn)LifeCycleOwner,可以實現(xiàn)LifecycleRegistryOwner這個接口言蛇。而不是繼承(LifeCycleFragment和LifeCycleActivity)

public class MyFragment extends Fragment implements LifecycleRegistryOwner {
    LifecycleRegistry lifecycleRegistry = new LifecycleRegistry(this);

    @Override
    public LifecycleRegistry getLifecycle() {
        return lifecycleRegistry;
    }
}

如果你要在自定義的類中實現(xiàn)LifeCycleOwner僻他,可以使用LifecycleRegistry,但是你需要主動向其轉(zhuǎn)發(fā)生命周期的事件。但如果你自定義類是Fragment和Activity的話并且它們實現(xiàn)的是LifecycleRegistryOwner腊尚,那么事件轉(zhuǎn)發(fā)都是自動完成的吨拗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市婿斥,隨后出現(xiàn)的幾起案子劝篷,更是在濱河造成了極大的恐慌,老刑警劉巖民宿,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件娇妓,死亡現(xiàn)場離奇詭異,居然都是意外死亡活鹰,警方通過查閱死者的電腦和手機(jī)哈恰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來志群,“玉大人着绷,你說我怎么就攤上這事⌒吭疲” “怎么了荠医?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長桑涎。 經(jīng)常有香客問我彬向,道長,這世上最難降的妖魔是什么攻冷? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任幢泼,我火速辦了婚禮,結(jié)果婚禮上讲衫,老公的妹妹穿的比我還像新娘。我一直安慰自己孵班,他們只是感情好涉兽,可當(dāng)我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著篙程,像睡著了一般枷畏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上虱饿,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天拥诡,我揣著相機(jī)與錄音触趴,去河邊找鬼。 笑死渴肉,一個胖子當(dāng)著我的面吹牛冗懦,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播仇祭,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼披蕉,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了乌奇?” 一聲冷哼從身側(cè)響起没讲,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎礁苗,沒想到半個月后爬凑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡试伙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年嘁信,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迁霎。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡吱抚,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出考廉,到底是詐尸還是另有隱情秘豹,我是刑警寧澤,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布昌粤,位于F島的核電站既绕,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏涮坐。R本人自食惡果不足惜凄贩,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望袱讹。 院中可真熱鬧疲扎,春花似錦、人聲如沸捷雕。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽救巷。三九已至壶熏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間浦译,已是汗流浹背棒假。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工溯职, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人帽哑。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓谜酒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親祝拯。 傳聞我的和親對象是個殘疾皇子甚带,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,933評論 2 355

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