Lifecycle

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

編寫說明,文章收錄于《Android Jetpack》,文章將大部分摘錄于
[官方教程]https://developer.android.google.cn/topic/libraries/architecture/lifecycle

1.核心功能

生命周期感知型組件可執行操作來響應另一個組件(如 Activity 和 Fragment)的生命周期狀態的變化。這些組件有助于您寫出更有條理且往往更精簡的代碼,這樣的代碼更易于維護。

一種常見的模式是在 Activity 和 Fragment 的生命周期方法中實現依賴組件的操作。但是,這種模式會導致代碼條理性很差而且會擴散錯誤。通過使用生命周期感知型組件,您可以將依賴組件的代碼從生命周期方法移入組件本身中。

androidx.lifecycle 軟件包提供了可用于構建生命周期感知型組件的類和接口 - 這些組件可以根據 Activity 或 Fragment 的當前生命周期狀態自動調整其行為。

以下以定位代碼為例:

1.以往的方式
常見的模式是在 Activity 和 Fragment 的生命周期方法中實現依賴組件的操作。

    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
        }
    }
    

2.使用生命周期感知型組件

MyLocationListener.java

    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
        }
    }
    

MyActivity.java

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

1、2是使用Lifecycle改造常規涉及Android組件(Activity)生命業務代碼的既簡單,又清晰的例子,至于部分代碼的含義,會在后續中做一些說明。

2.生命周期

Lifecycle 是一個類,用于存儲有關組件(如 Activity 或 Fragment)的生命周期狀態的信息,并允許其他對象觀察此狀態。

Lifecycle 使用兩種主要枚舉跟蹤其關聯組件的生命周期狀態:

事件
從框架和 Lifecycle 類分派的生命周期事件。這些事件映射到 Activity 和 Fragment 中的回調事件。

狀態
Lifecycle 對象跟蹤的組件的當前狀態。

圖片.png

您可以將狀態看作圖中的節點,將事件看作這些節點之間的邊。

類可以通過向其方法添加注解來監控組件的生命周期狀態。然后,您可以通過調用 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());
  

3、LifecycleOwner

LifecycleOwner 是單一方法接口,表示類具有 Lifecycle。它具有一種方法(即 getLifecycle()),該方法必須由類實現。如果您嘗試管理整個應用進程的生命周期,請參閱 ProcessLifecycleOwner

/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.lifecycle;

import androidx.annotation.NonNull;

/**
 * A class that has an Android lifecycle. These events can be used by custom components to
 * handle lifecycle changes without implementing any code inside the Activity or the Fragment.
 *
 * @see Lifecycle
 */
@SuppressWarnings({"WeakerAccess", "unused"})
public interface LifecycleOwner {
    /**
     * Returns the Lifecycle of the provider.
     *
     * @return The lifecycle of the provider.
     */
    @NonNull
    Lifecycle getLifecycle();
}

此接口從各個類(如 [Fragment](https://developer.android.google.cn/reference/androidx/fragment/app/Fragment)[AppCompatActivity](https://developer.android.google.cn/reference/androidx/appcompat/app/AppCompatActivity))抽象化 Lifecycle 的所有權,并允許編寫與這些類搭配使用的組件。任何自定義應用類均可實現 LifecycleOwner 接口。

實現 LifecycleObserver 的組件可與實現 LifecycleOwner 的組件無縫協同工作,因為所有者可以提供生命周期,而觀察者可以注冊以觀察生命周期。

對于位置跟蹤示例,我們可以讓 MyLocationListener 類實現 LifecycleObserver,然后在 [onCreate()](https://developer.android.google.cn/reference/android/app/Activity#onCreate(android.os.Bundle)) 方法中使用 Activity 的 Lifecycle 對其進行初始化。這樣,MyLocationListener 類便可以“自給自足”,這意味著,對生命周期狀態的變化做出響應的邏輯會在 MyLocationListener(而不是在 Activity)中進行聲明。讓各個組件存儲自己的邏輯,可使 Activity 和 Fragment 邏輯更易于管理。

以上就對位置跟蹤的示例做了一個說明

4.生命周期感知型組件的最佳做法

  • 使界面控制器(Activity 和 Fragment)盡可能保持精簡。它們不應試圖獲取自己的數據,而應使用 ViewModel 執行此操作,并觀察 LiveData 對象以將更改體現到視圖中。
  • 設法編寫數據驅動型界面,對于此類界面,界面控制器的責任是隨著數據更改而更新視圖,或者將用戶操作通知給 ViewModel
  • 將數據邏輯放在 ViewModel 類中。ViewModel 應充當界面控制器與應用其余部分之間的連接器。不過要注意,ViewModel 不負責獲取數據(例如,從網絡獲取)。ViewModel 應調用相應的組件來獲取數據,然后將結果提供給界面控制器。
  • 使用 Data Binding 在視圖與界面控制器之間維持干凈的接口。這樣一來,您可以使視圖更具聲明性,并盡量減少需要在 Activity 和 Fragment 中編寫的更新代碼。如果您更愿意使用 Java 編程語言執行此操作,請使用諸如 Butter Knife 之類的庫,以避免樣板代碼并實現更好的抽象化。
  • 如果界面很復雜,不妨考慮創建 presenter 類來處理界面的修改。這可能是一項艱巨的任務,但這樣做可使界面組件更易于測試。
  • 避免在 ViewModel 中引用 [View](https://developer.android.google.cn/reference/android/view/View)[Activity](https://developer.android.google.cn/reference/android/app/Activity) 上下文。如果 ViewModel 存在的時間比 Activity 更長(在配置更改的情況下),Activity 將泄露并且不會由垃圾回收器妥善處置。
  • 使用 Kotlin 協程管理長時間運行的任務和其他可以異步運行的操作。

5、生命周期感知型組件的用例

  • 在粗粒度和細粒度位置更新之間切換。使用生命周期感知型組件可在位置應用可見時啟用細粒度位置更新,并在應用位于后臺時切換到粗粒度更新。借助生命周期感知型組件 LiveData,應用可以在用戶使用位置發生變化時自動更新界面。
  • 停止和開始視頻緩沖。使用生命周期感知型組件可盡快開始視頻緩沖,但會推遲播放,直到應用完全啟動。此外,應用銷毀后,您還可以使用生命周期感知型組件終止緩沖。
  • 開始和停止網絡連接。借助生命周期感知型組件,可在應用位于前臺時啟用網絡數據的實時更新(流式傳輸),并在應用進入后臺時自動暫停。
  • 暫停和恢復動畫可繪制資源。借助生命周期感知型組件,可在應用位于后臺時暫停動畫可繪制資源,并在應用位于前臺后恢復可繪制資源。
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。