成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

用生命周期感知組件處理生命周期

acrazing / 986人閱讀

摘要:生命周期感知組件會執(zhí)行操作來響應另一個組件如和的生命周期狀態(tài)的改變。使用兩個主要枚舉來追蹤其關(guān)聯(lián)組件的生命周期狀態(tài)從和類中分發(fā)的生命周期事件,這些事件映射到和的回調(diào)事件中。

生命周期感知組件會執(zhí)行操作來響應另一個組件(如 activity 和 fragment)的生命周期狀態(tài)的改變。這些組件可以幫助你生成組織性更好、更輕量級、更易于維護的代碼。

一個常見的模式是在 activity 和 fragment 的生命周期方法中實現(xiàn)依賴組件的動作。但是,這種模式會導致代碼的組織不良以及錯誤的擴散。通過使用生命周期感知組件,可以將依賴組件的代碼從生命周期方法中轉(zhuǎn)移到組件本身。

android.arch.lifecycle 包提供了一些類和接口,讓你可以構(gòu)建生命周期感知組件,這些組件可以根據(jù)活動或片段的當前生命周期狀態(tài)自動調(diào)整自己的行為。

注意:要將?android.arch.lifecycle?包導入到你的 Android 項目中, 請參閱?adding components to your project。

Android Framework 中定義的大多數(shù)應用程序組件都附帶有生命周期。生命周期由操作系統(tǒng)或在你的進程中運行的框架代碼進行管理。它們是 Android 工作的核心,你的應用程序必須尊重它們。不這樣做可能會觸發(fā)內(nèi)存泄漏,甚至導致應用程序崩潰。

想象一下,我們有一個在屏幕上顯示設備位置的 Activity 。常見的實現(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;

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

    @Override
    public void onStart() {
        super.onStart();
        myLocationListener.start();
        // manage other components that need to respond
        // to the activity lifecycle
    }

    @Override
    public void onStop() {
        super.onStop();
        myLocationListener.stop();
        // manage other components that need to respond
        // to the activity lifecycle
    }
}

即使這個示例看起來不錯,但是在真實應用中,你最終會有太多的調(diào)用來管理UI和其他組件,以響應當前的生命周期狀態(tài)。 管理多個組件會在生命周期方法中放置大量代碼,例如 onStart() 和 onStop(),這使得維護變得困難。

而且,組件在 activity 或 fragment 被停止之前啟動是無法保證的。如果我們執(zhí)行一個長時間運行的操作,比如在 onStart() 進行一些配置檢查,則尤其如此。這會導致一種競速的狀況,這種狀況是 onStop() 方法在 onStart() 之前結(jié)束,使組件存活的時間比他需要的時間更長。

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

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

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

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

android.arch.lifecycle 包提供的類和接口可以幫助你以彈性和獨立的方式解決這些問題。

Lifecycle

Lifecycle 是一個類,它保存組件(如 activity 或 fragment)的生命周期狀態(tài)信息,并允許其他對象觀察此狀態(tài)。

Lifecycle 使用兩個主要枚舉來追蹤其關(guān)聯(lián)組件的生命周期狀態(tài):

Event

?從 framework 和 Lifecycle 類中分發(fā)的生命周期事件,這些事件映射到 activity 和 fragment 的回調(diào)事件中。

State

?Lifecycle 對象追蹤的組件的當前狀態(tài)。

把 states 看作圖形的節(jié)點,events 看作這些節(jié)點的邊。

一個類可以通過給它的方法添加注解來監(jiān)聽組件的生命周期,然后,你可以通過調(diào)用 Lifecycle 類的 addObserver() 方法,傳遞一個觀察者實例來添加一個觀察者,如下示例所示:

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());

在上面的示例中,myLifecycleOwner 對象實現(xiàn)了 LifecycleOwner 接口,下一節(jié)會對其進行解釋。

LifecycleOwner

LifecycleOwner是一個表示該類有一個 Lifecycle 的單方法接口。它有一個必須被該類實現(xiàn)的 getLifecycle() 方法。如果你試圖去管理整個應用程序進程的生命周期,請參閱 ProcessLifecycleOwner。

這個接口從各個類(如 Fragment 和 AppCompatActivity)提取 Lifecycle 的所有權(quán),并允許編寫與它們一起工作的組件。任何自定義的應用程序類都可以實現(xiàn) LifecycleOwner 接口。

實現(xiàn) LifecycleObserver 的組件與實現(xiàn) LifecycleOwner的組件無縫協(xié)作,因為 owner 可以提供 observer 可以注冊的生命周期。

對位置追蹤示例來說,我們可以讓 MyLocationListener 類實現(xiàn) LifecycleObserver,然后 在 onCreate() 方法中 用 activity 的 Lifecycle 來初始化它。這允許 MyLocationListener 類自給自足,意味著對生命周期狀態(tài)的變化做出反應的邏輯是在
MyLocationListener 而不是 activity 中聲明的。讓各個組件存儲自己的邏輯使得 activity 和 fragment 的邏輯更容易管理。

class MyActivity extends AppCompatActivity {
    private MyLocationListener myLocationListener;

    public void onCreate(...) {
        myLocationListener = new MyLocationListener(this, getLifecycle(), location -> {
            // update UI
        });
        Util.checkUserStatus(result -> {
            if (result) {
                myLocationListener.enable();
            }
        });
  }
}

一個常見的用例是,如果現(xiàn)在 Lifecycle 不在一個好的狀態(tài),那么避免調(diào)用某些 callback。例如,如果 callback 在 activity 狀態(tài)被保存之后執(zhí)行一個 fragment 事務,會觸發(fā)崩潰,所以我們絕對不會調(diào)用該 callback。

為了簡化這個用例,Lifecycle 類允許其他對象查詢當前狀態(tài)。

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.getCurrentState().isAtLeast(STARTED)) {
            // connect if not connected
        }
    }

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

通過這個實現(xiàn),我們的 LocationListener 類是完全生命周期感知的。如果我們需要從其他 activity 或 fragment 中使用我們的 LocationListener,我們只需要初始化它。所有的設置和刪除操作都是由類自身管理。

如果一個庫提供了需要使用 Android 生命周期工作的類,我們建議你使用生命周期感知組件。庫客戶端可以輕松地集成這些組件,而無須在客戶端進行手動生命周期管理。

實現(xiàn)一個自定義的 LifecycleOwner

26.1.0 及更高版本的 Support Library 中的 Fragments and Activities 已經(jīng)實現(xiàn)了 LifecycleOwner 接口。

如果你有一個想要作為 LifecycleOwner 的自定義類,你可以使用 LifecycleRegistry 類,但是你需要將事件轉(zhuǎn)發(fā)到該類中,如下代碼所示:

public class MyActivity extends Activity implements LifecycleOwner {
    private LifecycleRegistry mLifecycleRegistry;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mLifecycleRegistry = new LifecycleRegistry(this);
        mLifecycleRegistry.markState(Lifecycle.State.CREATED);
    }

    @Override
    public void onStart() {
        super.onStart();
        mLifecycleRegistry.markState(Lifecycle.State.STARTED);
    }

    @NonNull
    @Override
    public Lifecycle getLifecycle() {
        return mLifecycleRegistry;
    }
}
生命周期感知組件的最佳實踐

保持 UI 控制器盡可能精簡,它們不應該試圖獲取自己的數(shù)據(jù),作為替代,使用 ViewModel 來做到這一點,并觀察一個 LiveData 對象,將變化反映給視圖。

嘗試編寫數(shù)據(jù)驅(qū)動的 UI,該 UI 的 UI 控制器的職責是在數(shù)據(jù)變化時更新視圖,或者將用戶操作通知給ViewModel。

把數(shù)據(jù)邏輯放在 ViewModel 類中, ViewModel 應該充當 UI 控制器和應用程序其他部分的連接器。但是要小心,獲取數(shù)據(jù)(例如從網(wǎng)絡)并不是 ViewModel 的職責,作為替代, ViewModel 應該調(diào)用適當?shù)慕M件來獲取數(shù)據(jù),然后將結(jié)果提供給 UI 控制器。

使用 Data Binding 在視圖和 UI 控制器之間維護一個清爽的接口。這允許你讓視圖更具聲明性,并最大限度的減少需要在 activities 和 fragments 中寫入的更新代碼。如果你更喜歡用 Java 編程語言來實現(xiàn)這一點,請使用類似 Butter Knife 的庫來避免樣板代碼,并具有更好的抽象。

如果你的 UI 很復雜,請考慮創(chuàng)建一個 presenter 類來處理 UI 修改。這可能是一項艱巨的任務,但它可以使 UI 組件更易于測試。

避免在 ViewModel 中引用View 或 Activity 上下文。如果 ViewModel 存活時間比 activity 更長(在配置更改的情況下),那么 activity 會泄露,并且無法被 GC 正確處理。

生命周期感知組件的用例

生命周期感知組件可以使你在各種情況下更容易管理生命周期。這里是一些例子:

在粗略和精細的位置信息更新之前切換。使用生命周期感知組件,在 location app 可見時啟用精細的位置更新,當應用處于后臺時切換到粗略的位置更新。LiveData 是一種生命周期感知組件,它允許應用程序在位置改變時自動更新 UI。

停止和啟動視頻緩沖。使用生命周期感知組件盡快啟動視頻緩沖,但是將播放推遲到應用完全啟動的時候。你也可以使用生命周期感知組件在應用銷毀時終止緩沖。

啟動和停止網(wǎng)絡連接。使用生命周期感知組件,在應用處于前臺時啟動網(wǎng)絡數(shù)據(jù)傳輸,在應用進入后臺時自動暫停。

暫停和恢復動畫繪制。使用生命周期感知組件,在應用處于后臺時暫停動畫繪制,當應用處于前臺時恢復繪制。

處理停止事件

當 Lifecycle 屬于AppCompatActivity 或 Fragment ,在 AppCompatActivity 或 Fragment 的 onSaveInstanceState() 被調(diào)用時,Lifecycle 的狀態(tài)改變?yōu)镃REATED,ON_STOP 事件被分發(fā)。

當 Fragment 或 AppCompatActivity 的狀態(tài)通過 onSaveInstanceState() 保存時,直到 ON_START 被調(diào)用為止,它的 UI 被認為是不可變的。嘗試在保存狀態(tài)后修改 UI,可能會導致應用的導航狀態(tài)不一致,這就是如果應用程序在保存狀態(tài)后運行 FragmentManager,F(xiàn)ragmentManager 拋出異常的原因,詳情請參閱 commit()。

如果 observer 關(guān)聯(lián)的 Lifecycle 的狀態(tài)至少不是 STARTED,LiveData 可以通過避免調(diào)用它的 observer 來防止這種極端情況的出現(xiàn)。在幕后,它在決定調(diào)用 observer 之前調(diào)用了 isAtLeast()。

不幸的是,AppCompatActivity 的 onStop() 方法是在 onSaveInstanceState() 之后被調(diào)用的,這會在 UI 狀態(tài)更改不被允許但 Lifecycle 還沒有移至 CREATED 狀態(tài)情況下留下空隙。

為了避免這個問題,beta2 和更低版本的 Lifecycle 類,將狀態(tài)標記為 CREATED,而不分發(fā)事件,這樣任何檢查當前狀態(tài)的代碼都會得到真實值,即使事件直到 onStop() 被系統(tǒng)調(diào)用才會被分發(fā)。

不幸的是,這個解決方案有兩個主要問題:

在 API 23及更低版本上,Android 系統(tǒng)實際上保存了 activity 的狀態(tài),即使它被另一個 activity 部分覆蓋。換句話說,Android 系統(tǒng)調(diào)用 onSaveInstanceState(),但不一定調(diào)用 onStop()。這會產(chǎn)生一個潛在的長時間間隔,即使其 UI 狀態(tài)不能被修改,觀察者仍認為生命周期是活動的。

任何想要暴露類似行為給 LiveData 類的類必須實現(xiàn) beta 2以下版本 Lifecycle 提供的變通方法。

注意:為了使這個流程更簡單,并提供與舊版本更好的兼容性,從 1.0.0-rc1 開始,Lifecycle 對象被標記為CREATED ,并且在 onSaveInstanceState() 被調(diào)用時分發(fā) ON_STOP,而不等待 onStop() 方法的調(diào)用。這不太可能影響你的代碼,但你需要注意的是,這與 API 26 以下的 Activity 中的調(diào)用順序不匹配。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/70824.html

相關(guān)文章

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<