Android官方架構組件介紹之LifeCycle(一)

Android官方架構組件介紹之LifeCycleandroid

下面是官方提供的Android App開發的架構圖:網絡

 

從上圖能夠看到一些關鍵字:ViewModel,LiveData,Room等。其實看了上面視頻的會發現Google官方Android架構組件一共包括如下幾個:架構

  • LifeCycle : 與Activity和Fragment的生命週期有關
  • LiveData :異步可訂閱數據,也是生命週期感知
  • ViewModel :視圖數據持有模型,也是生命週期感知
  • Room :SQLite抽象層,用於簡化SQLite數據存儲

這篇文章主要講解LifeCycle在項目的簡單用法異步

AS中添加依賴

首先在工程根目錄的build.gradle中添加一下內容:maven

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

而後在應用目錄下的build.gradle中添加如下依賴:ide

//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相關使用

在咱們平時的項目中常常會遇到不少須要依賴生命週期的邏輯處理,好比有這麼一個需求。
在某個Activity咱們須要在屏幕上展示用戶的地理位置。簡單的實現方法以下:測試

lass 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方法可能會變得至關龐大。
此外,實際狀況可能並不像上面這麼簡單,例如咱們須要在start位置監聽前作用戶狀態檢測,檢測是一個耗時的任務,那麼頗有可能在檢測結束前用戶提早退出了Activity,這時候就會致使myLocationListener.start()myLocationListener.stop()後面調用,從而引發不少難以定位的問題。代碼以下:gradle

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出場了。它提供了一套接口幫助你處理這些問題。ui

LifeCycle

LifeCyle類持有Activity或者Fragment的生命週期相關信息,而且支持其餘對象監聽這些狀態。this

LifeCyle有兩個枚舉用於追蹤生命週期中的狀態。

Event

這是生命週期的事件類,會在Framework和LifeCycle間傳遞,這些事件映射到Activity和Fragment的回調事件中。

State

LifeCycle所持有Activity或Fragment的當前狀態。

一個類想要監聽LifeCycle的狀態,只須要給其方法加上註解:

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,Fragment和LifeCycle提供了一個很好的抽象關係,Activity和Fragment只要實現這個接口就能配合LifeCycle實現生命週期監聽。

注意:因爲目前LifeCycle處於alpha階段,因此Fragment和AppCompatActivity並不會實現這些方法,在此以前,可使用LifecycleActivityLifecycleFragment。等LifeCycle趨於穩定後,Fragment和AppCompatActivity會默認實現這些。

對於以前的位置監聽的例子,咱們可讓MyLocationListener繼承LifecycleObserver,在onCreate中使用LifeCycle進行初始化,剩下的問題則沒必要擔憂了。由於MyLocationListener有能力進行生命週期的判斷。

class MyActivity extends LifecycleActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        //此處進行初始化getLifecycle()傳入LifeCycle對象
        myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
            // update UI
        });
        //檢測用戶狀態並啓用監聽
        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最重要的特性就是在⓵處,他能夠提供主動查詢生命週期狀態的方法。這樣就避免了上面遇到的myLocationListener.start()myLocationListener.stop()後面調用的問題。

經過以上的實現,咱們的LocationListener是徹底的生命週期感知了,它能夠進行本身的初始化和資源清理而沒必要受Activity或者Fragment的管理。這時候若是咱們在其餘Activity或者Fragment中使用LocationListener,咱們只須要初始化它就好了,沒必要再擔憂生命週期對它的影響,由於它內部會作好這一切。

經過LefeCycle工做的類咱們稱之爲生命週期感知。鼓勵須要使用Android生命週期的類的庫提供生命週期感知組件,以便客戶端能夠輕鬆地在客戶端上集成這些類,而無需手動生命週期管理。

LiveData就是生命週期感知組件的示例,將LiveData和ViewModel一塊兒使用,能夠在遵循Android生命週期的狀況下,更容易的使用數據來填充UI。

生命週期的最佳實踐

  • 保持你的UI(Activity和Fragment)儘量簡潔。它們不該該試圖獲取它們的數據而是使用ViewModel來執行此操做,並經過LiveData的回調將數據更新到UI中。
  • 嘗試編寫數據驅動的UI,你的UI的責任是在數據更改時更新視圖,或將用戶操做通知給ViewModel。
  • 將你的數據邏輯放在ViewModel類中。 ViewModel應該做爲UI和其餘數據操做的鏈接器。值得注意的是,ViewModel並不負責提取數據(例如,從網絡)。相反,ViewModel應該調用其餘接口來執行此工做,而後將結果提供給UI。
  • 使用Data Binding可讓你的的UI代碼變得至關乾淨利落。這將使你的UI更具聲明性,並最大限度地減小書寫UI更新的代碼。若是您更喜歡在Java中執行此操做,請使用像Butter Knife這樣的庫來避免使用樣板代碼並進行更好的抽象。
  • 若是你有一個複雜的UI,請考慮建立一個Presenter類來處理UI修改。這一般是過分架構的,但可能有助於使你的UI更容易測試。
  • 不要在ViewModel中引用View或Activity上下文。若是ViewModel在Activity或View銷燬的狀況下依舊存活,這時將致使內存泄漏。

補充

在自定義的Activity或Fragment中實現LifeCycleOwner,能夠實現LifecycleRegistryOwner這個接口。而不是繼承(LifeCycleFragment和LifeCycleActivity)

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

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

若是你要在自定義的類中實現LifeCycleOwner,可使用LifecycleRegistry,可是你須要主動向其轉發生命週期的事件。但若是你自定義類是Fragment和Activity的話而且它們實現的是LifecycleRegistryOwner,那麼事件轉發都是自動完成的。

相關文章
相關標籤/搜索