banner
jzman

jzman

Coding、思考、自觉。
github

Android JetpackコンポーネントのLifecycle編

ライフサイクル対応コンポーネントは、Android Jetpack の一部であり、このコンポーネントは Activity と Fragment のライフサイクル状態の変化を感知することができ、より整理された、軽量で、メンテナンスしやすいコードの生成に役立ちます。一般的な開発方法は、コンポーネントの対応するライフサイクルメソッド内で関連するビジネスロジックを処理することですが、この方法は悪いコードの生成やバグの増加を引き起こす可能性があります。ライフサイクルコンポーネントを使用することで、依存コンポーネントのコードをライフサイクルから削除し、コンポーネント自体に移動させることができます。

  1. ライフサイクル
  2. ライフサイクルのソースコード分析
  3. ProcessLifecycleOwner の初期化

ライフサイクル#

ライフサイクルは、コンポーネントのライフサイクル状態情報を保持する抽象クラスで、その直接のサブクラスは LifecycleRegistry です。Activity と Fragment は、間接的に LifecycleOwner インターフェースを実装しており、対応する getLifecycle メソッドを提供してライフサイクルオブジェクトを取得します。取得されるのは LifecycleRegistry オブジェクトです。以下はライフサイクルのライフサイクルに対応する状態図です:

image

図示されている主な点は、Event(イベント)と Status(状態)です。

  • Event:ON_CREATE、ON_START など、Activity または Fragment に対応するライフサイクルメソッド
  • Status:ライフサイクル内のライフサイクルが存在する状態。上の図では、ON_CREATE と ON_STOP の次の状態は CREATED 状態であり、具体的なライフサイクルイベントと状態を対応させることができます。

開発環境が Java1.7 の場合、注釈を使用してライフサイクルの変化を監視することができます。以下を参照してください:

/**
 * Powered by jzman.
 * Created on 2018/12/8 0008.
 */
public class LifeCycleListener implements LifecycleObserver {

    private static final String TAG = LifeCycleListener.class.getSimpleName();

    @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
    private void onCreate(LifecycleOwner owner) {
        Log.i(TAG,"--onCreate-->");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    private void onStart(LifecycleOwner owner) {
        Log.i(TAG,"--onStart-->");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    private void onResume(LifecycleOwner owner) {
        Log.i(TAG,"--onResume-->");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    private void onPause(LifecycleOwner owner) {
        Log.i(TAG,"--onPause-->");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    private void onStop(LifecycleOwner owner) {
        Log.i(TAG,"--onStop-->");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    private void onDestroy(LifecycleOwner owner) {
        Log.i(TAG,"--onDestroy-->");
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    private void onAny(LifecycleOwner owner, Lifecycle.Event event) {
        //onAnyメソッドには第二引数を追加して、現在のライフサイクルを取得できます
        //どんなライフサイクル状態の変化でもトリガーされます
        Log.i(TAG,"--onAny-->"+event.name());
    }
}

開発環境が Java1.8 の場合、DefaultLifecycleObserver インターフェースを実装する方法でライフサイクルの変化を監視することをお勧めします。まず、対応するモジュールの build.gradle ファイルに以下を追加します:

implementation "android.arch.lifecycle:common-java8:1.1.1"

次に、ライフサイクルリスナーを以下のように作成します:

/**
 * Powered by jzman.
 * Created on 2018/12/10 0010.
 */
public class LifeCycleListener1 implements DefaultLifecycleObserver {

    private static final String TAG = LifeCycleListener.class.getSimpleName();

    @Override
    public void onCreate(@NonNull LifecycleOwner owner) {
        Log.i(TAG,"--onCreate-->");
    }

    @Override
    public void onStart(@NonNull LifecycleOwner owner) {
        Log.i(TAG,"--onStart-->");
    }

    @Override
    public void onResume(@NonNull LifecycleOwner owner) {
        Log.i(TAG,"--onResume-->");
    }

    @Override
    public void onPause(@NonNull LifecycleOwner owner) {
        Log.i(TAG,"--onPause-->");
    }

    @Override
    public void onStop(@NonNull LifecycleOwner owner) {
        Log.i(TAG,"--onStop-->");
    }

    @Override
    public void onDestroy(@NonNull LifecycleOwner owner) {
        Log.i(TAG,"--onDestroy-->");
    }
}

最後に、対応する Activity または Fragment でこのリスナーを登録します。以下を参照してください:

LifeCycleListener mLifeCycleListener = new LifeCycleListener();
getLifecycle().addObserver(mLifeCycleListener);

LifeCycleListener の例として、ライフサイクルリスナーが Activity のライフサイクルの実行ログは以下の通りです:

//Activityを開く
 --onCreate-->
--onAny-->ON_CREATE
--onStart-->
--onAny-->ON_START
--onResume-->
--onAny-->ON_RESUME
//Activityを終了する
--onPause-->
--onAny-->ON_PAUSE
--onStop-->
--onAny-->ON_STOP
--onDestroy-->
--onAny-->ON_DESTROY

ライフサイクルのソースコード分析#

LifecycleOwner はインターフェースであり、このインターフェースを実装するクラスはライフサイクルを持つことを示します。すべての AppCompatActivity を継承する Activity は、間接的に LifecycleOwner インターフェースを実装しています。ソースコードでは ComponentActivity がこのインターフェースを実装しています。実際の開発では、LifecycleOwner インターフェースを実装して、元の Activity または Fragment のライフサイクルで実行されるビジネスをコンポーネント自体に移動させることができます。

上記の文から、getLifecycle () を使用して取得されるのは、ライフサイクルの具体的な実装クラスである LifecycleRegistry オブジェクトです。その後、addObserver を使用して LifecycleObserver オブジェクトを追加します。つまり、通知される観察者を追加します。その後、Activity または Fragment のライフサイクルが変化したときに観察者が通知されることになりますが、Activity のライフサイクルはどのように感知されるのでしょうか。

ComponentActivity では、Activity のライフサイクルを感知するために無界面の Fragment が追加されています。ソースコードは以下の通りです:

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mSavedStateRegistryController.performRestore(savedInstanceState);
    //ActivityにFragmentを追加
    ReportFragment.injectIfNeededIn(this);
}

injectIfNeededIn メソッドは、ReportFragment という名前の Fragment を作成します。Activity が作成されるたびに、この Fragment が対応する Activity に追加されます。ReportFragment のソースコードは以下の通りです:

public class ReportFragment extends Fragment {
    
    // Fragmentを作成
    public static void injectIfNeededIn(Activity activity) {
        android.app.FragmentManager manager = activity.getFragmentManager();
        //一度だけ追加することを保証
        if (manager.findFragmentByTag(REPORT_FRAGMENT_TAG) == null) {
            manager.beginTransaction().add(new ReportFragment(), REPORT_FRAGMENT_TAG).commit();
            manager.executePendingTransactions();
        }
    }

    //...

    // Activityの初期化リスナー、Activityのライフサイクル状態を監視
    private ActivityInitializationListener mProcessListener;

    // Activityライフサイクル状態の分配
    private void dispatchCreate(ActivityInitializationListener listener) {
        if (listener != null) {
            listener.onCreate();
        }
    }
    private void dispatchStart(ActivityInitializationListener listener) {
        if (listener != null) {
            listener.onStart();
        }
    }
    private void dispatchResume(ActivityInitializationListener listener) {
        if (listener != null) {
            listener.onResume();
        }
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // 対応するライフサイクル状態を分配
        dispatchCreate(mProcessListener);
        dispatch(Lifecycle.Event.ON_CREATE);
    }

    @Override
    public void onStart() {
        super.onStart();
        dispatchStart(mProcessListener);
        dispatch(Lifecycle.Event.ON_START);
    }

    @Override
    public void onResume() {
        super.onResume();
        dispatchResume(mProcessListener);
        dispatch(Lifecycle.Event.ON_RESUME);
    }

    @Override
    public void onPause() {
        super.onPause();
        dispatch(Lifecycle.Event.ON_PAUSE);
    }

    @Override
    public void onStop() {
        super.onStop();
        dispatch(Lifecycle.Event.ON_STOP);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        dispatch(Lifecycle.Event.ON_DESTROY);
        // アクティビティへの参照が漏れないようにするため
        mProcessListener = null;
    }

    // ライフサイクル状態を分配
    private void dispatch(Lifecycle.Event event) {
       // LifecycleRegistryOwnerは廃止されているが、互換性のために残されている
        Activity activity = getActivity();
        if (activity instanceof LifecycleRegistryOwner) {
            ((LifecycleRegistryOwner) activity).getLifecycle().handleLifecycleEvent(event);
            return;
        }
        
        // Activity内のライフサイクルを取得
        if (activity instanceof LifecycleOwner) {
            Lifecycle lifecycle = ((LifecycleOwner) activity).getLifecycle();
            if (lifecycle instanceof LifecycleRegistry) {
                // Activityライフサイクル状態を分配
                ((LifecycleRegistry) lifecycle).handleLifecycleEvent(event);
            }
        }
    }

    void setProcessListener(ActivityInitializationListener processListener) {
        mProcessListener = processListener;
    }
    
    // Activity初期化リスナー
    interface ActivityInitializationListener {
        void onCreate();

        void onStart();

        void onResume();
    }
}

ReportFragment の対応するライフサイクルメソッド内でライフサイクル状態の分配が行われていることがわかります。分配プロセスは dispatch メソッドに対応しており、その中で handleLifecycleEvent メソッドが呼び出されます。このメソッドは後で紹介しますが、Activity のライフサイクルの監視は ActivityInitializationListener 内で完了します。このインターフェースの実装クラスは匿名内部クラスであり、ProcessLifecycleOwner 内に位置しています。ソースコードは以下の通りです:

public class ProcessLifecycleOwner implements LifecycleOwner {
    // ...
    
    private Handler mHandler;
    private final LifecycleRegistry mRegistry = new LifecycleRegistry(this);

    private Runnable mDelayedPauseRunnable = new Runnable() {
        @Override
        public void run() {
            dispatchPauseIfNeeded();
            dispatchStopIfNeeded();
        }
    };

    // ActivityInitializationListenerの匿名実装クラス
    private ActivityInitializationListener mInitializationListener =
            new ActivityInitializationListener() {
                @Override
                public void onCreate() {
                    // 何?
                    // なぜ処理しないのか、ソースコードの読みやすさに影響しない
                }

                @Override
                public void onStart() {
                    activityStarted();
                }

                @Override
                public void onResume() {
                    activityResumed();
                }
            };

    private static final ProcessLifecycleOwner sInstance = new ProcessLifecycleOwner();

    // 初期化、どこで初期化されるのか?——>後の文を参照
    static void init(Context context) {
        sInstance.attach(context);
    }

    void activityStarted() {
        mStartedCounter++;
        if (mStartedCounter == 1 && mStopSent) {
            // ON_START や ON_RESUME など、重要なのは handleLifecycleEvent メソッド
            mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
            mStopSent = false;
        }
    }

    void activityResumed() {
        mResumedCounter++;
        if (mResumedCounter == 1) {
            if (mPauseSent) {
                mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
                mPauseSent = false;
            } else {
                mHandler.removeCallbacks(mDelayedPauseRunnable);
            }
        }
    }

    void activityPaused() {
        mResumedCounter--;
        if (mResumedCounter == 0) {
            mHandler.postDelayed(mDelayedPauseRunnable, TIMEOUT_MS);
        }
    }

    void activityStopped() {
        mStartedCounter--;
        dispatchStopIfNeeded();
    }
    private void dispatchPauseIfNeeded() {
        if (mResumedCounter == 0) {
            mPauseSent = true;
            mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
        }
    }
    private void dispatchStopIfNeeded() {
        if (mStartedCounter == 0 && mPauseSent) {
            mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
            mStopSent = true;
        }
    }
    
    void attach(Context context) {
        mHandler = new Handler();
        mRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
        Application app = (Application) context.getApplicationContext();
        // Lifecycle コンポーネントがない場合、ActivityLifecycleCallbacks を使用してすべての Activity のライフサイクルを監視
        app.registerActivityLifecycleCallbacks(new EmptyActivityLifecycleCallbacks() {
            @Override
            public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
                ReportFragment.get(activity).setProcessListener(mInitializationListener);
            }

            @Override
            public void onActivityPaused(Activity activity) {
                activityPaused();
            }

            @Override
            public void onActivityStopped(Activity activity) {
                activityStopped();
            }
        });
    }
}

Lifecycle コンポーネントがない場合、ActivityLifecycleCallbacks を使用して Application にすべての Activity のライフサイクルを監視するために登録されます。ここでも ActivityLifecycleCallbacks が使用されていますが、監視対象は単一の Activity に変わり、より柔軟に使用できるようになります。

備考:上記には一つの問題があります。ProcessLifecycleOwner はどのように初期化されるのでしょうか?その答えは後の小節にあります。

上記の分析から、最終的なライフサイクル状態の分配は LifecycleRegistry の handleLifecycleEvent メソッド内で行われ、その中で sync メソッドが呼び出されます。ソースコードは以下の通りです:

private void sync() {
    LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
    if (lifecycleOwner == null) {
        Log.w(LOG_TAG, "LifecycleOwner がガーベジコレクションされました。新しいイベントをそこから送信しないでください。");
        return;
    }

    while (!isSynced()) {
        mNewEventOccurred = false;
        // eldest の null 性を確認する必要はありません。isSynced がそれを確認します。
        if (mState.compareTo(mObserverMap.eldest().getValue().mState) < 0) {
            backwardPass(lifecycleOwner);
        }
        Entry<LifecycleObserver, ObserverWithState> newest = mObserverMap.newest();
        if (!mNewEventOccurred && newest != null
                && mState.compareTo(newest.getValue().mState) > 0) {
            // 重要なメソッド
            forwardPass(lifecycleOwner);
        }
    }
    mNewEventOccurred = false;
}

forwardPass メソッドをさらに確認すると、ソースコードは以下の通りです:

private void forwardPass(LifecycleOwner lifecycleOwner) {
    Iterator<Entry<LifecycleObserver, ObserverWithState>> ascendingIterator =
            mObserverMap.iteratorWithAdditions();
    while (ascendingIterator.hasNext() && !mNewEventOccurred) {
        Entry<LifecycleObserver, ObserverWithState> entry = ascendingIterator.next();
        ObserverWithState observer = entry.getValue();
        while ((observer.mState.compareTo(mState) < 0 && !mNewEventOccurred
                && mObserverMap.contains(entry.getKey()))) {
            pushParentState(observer.mState);
            // ライフサイクル状態の分配
            observer.dispatchEvent(lifecycleOwner, upEvent(observer.mState));
            popParentState();
        }
    }
}

dispatchEvent メソッドをさらに確認すると、以下のようになります:

static class ObserverWithState {
        State mState;
        GenericLifecycleObserver mLifecycleObserver;

        ObserverWithState(LifecycleObserver observer, State initialState) {
            // observer に基づいて対応するタイプの GenericLifecycleObserver を生成
            mLifecycleObserver = Lifecycling.getCallback(observer);
            mState = initialState;
        }

        void dispatchEvent(LifecycleOwner owner, Event event) {
            State newState = getStateAfter(event);
            mState = min(mState, newState);
            // ライフサイクル状態をコールバック
            mLifecycleObserver.onStateChanged(owner, event);
            mState = newState;
        }
    }

慣例に従って、GenericLifecycleObserver の実装クラスを確認すると、onStateChanged メソッド内でライフサイクル状態の分配が行われることがわかります。具体的にどの GenericLifecycleObserver の実装クラスが使用されるかは、getCallback メソッドに渡される observer に依存します。getCallback メソッドのソースコードは以下の通りです:

 @NonNull
static GenericLifecycleObserver getCallback(Object object) {
    // DefaultLifecycleObserver を直接継承した場合
    if (object instanceof FullLifecycleObserver) {
        return new FullLifecycleObserverAdapter((FullLifecycleObserver) object);
    }
    // 推測:ライフサイクルを管理する際に、カスタムの Observer が GenericLifecycleObserver を継承している場合
    if (object instanceof GenericLifecycleObserver) {
        return (GenericLifecycleObserver) object;
    }

    // 注釈処理器(Annotation Processor)を使用している場合
    final Class<?> klass = object.getClass();
    int type = getObserverConstructorType(klass);
    if (type == GENERATED_CALLBACK) {
        List<Constructor<? extends GeneratedAdapter>> constructors =
                sClassToAdapters.get(klass);
        if (constructors.size() == 1) {
            GeneratedAdapter generatedAdapter = createGeneratedAdapter(
                    constructors.get(0), object);
            return new SingleGeneratedAdapterObserver(generatedAdapter);
        }
        GeneratedAdapter[] adapters = new GeneratedAdapter[constructors.size()];
        for (int i = 0; i < constructors.size(); i++) {
            adapters[i] = createGeneratedAdapter(constructors.get(i), object);
        }
        return new CompositeGeneratedAdaptersObserver(adapters);
    }
    return new ReflectiveGenericLifecycleObserver(object);
}

DefaultLifecycleObserver を直接継承する場合、FullLifecycleObserverAdapter が生成されます。このクラスの実装された onStateChanged コールバックメソッド内で、最終的なライフサイクル状態が分配されます。これにより、最初に作成した LifecycleListener1 で Activity のライフサイクル状態を監視できるようになります。FullLifecycleObserverAdapter のソースコードは以下の通りです:

class FullLifecycleObserverAdapter implements GenericLifecycleObserver {

    private final FullLifecycleObserver mObserver;

    FullLifecycleObserverAdapter(FullLifecycleObserver observer) {
        mObserver = observer;
    }

    @Override
    public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        // 具体的な Event に基づいて対応するライフサイクルメソッドにコールバック
        switch (event) {
            case ON_CREATE:
                mObserver.onCreate(source);
                break;
            case ON_START:
                mObserver.onStart(source);
                break;
            case ON_RESUME:
                mObserver.onResume(source);
                break;
            case ON_PAUSE:
                mObserver.onPause(source);
                break;
            case ON_STOP:
                mObserver.onStop(source);
                break;
            case ON_DESTROY:
                mObserver.onDestroy(source);
                break;
            case ON_ANY:
                throw new IllegalArgumentException("ON_ANY は誰にも送信されるべきではありません");
        }
    }
}

ProcessLifecycleOwner の初期化#

Activity のライフサイクル状態の監視には ActivityLifecycleCallbacks が使用されており、ActivityLifecycleCallbacks の登録は Application で行われます。では、どのように登録されるのでしょうか。その登録は ProcessLifecycleOwner の初期化中に行われます。ProcessLifecycleOwner の init メソッドの呼び出しは、ProcessLifecycleOwnerInitializer の onCreate メソッド内で行われます。ソースコードは以下の通りです:

public class ProcessLifecycleOwnerInitializer extends ContentProvider {
    @Override
    public boolean onCreate() {
        LifecycleDispatcher.init(getContext());
        // ProcessLifecycleOwner を初期化
        ProcessLifecycleOwner.init(getContext());
        return true;
    }

    // ...
}

明らかに ProcessLifecycleOwnerInitializer は ContentProvider であり、その onCreate メソッド内で ProcessLifecycleOwner を初期化するだけでなく、最初に LifecycleDispatcher を初期化しています。LifecycleDispatcher のソースコードは以下の通りです:

class LifecycleDispatcher {

    private static AtomicBoolean sInitialized = new AtomicBoolean(false);
    // LifecycleDispatcher の初期化
    static void init(Context context) {
        if (sInitialized.getAndSet(true)) {
            return;
        }
        // ActivityLifecycleCallbacks を登録
        ((Application) context.getApplicationContext())
                .registerActivityLifecycleCallbacks(new DispatcherActivityCallback());
    }

    @SuppressWarnings("WeakerAccess")
    @VisibleForTesting
    static class DispatcherActivityCallback extends EmptyActivityLifecycleCallbacks {

        @Override
        public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
            // Activity に無界面の Fragment を追加
            ReportFragment.injectIfNeededIn(activity);
        }

        @Override
        public void onActivityStopped(Activity activity) {
        }

        @Override
        public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
        }
    }

    private LifecycleDispatcher() {
    }
}

前述の分析を考慮すると、ここで登録される ActivityLifecycleCallbacks と前述の登録された ActivityLifecycleCallbacks の役割は完全に異なります。ここでは、Activity に無界面の Fragment を追加するために使用され、前述のものは Activity のライフサイクル状態を分配するために使用されます。Activity に無界面の Fragment を追加することを保証するために、前後で二回追加されることがわかります。ただし、injectIfNeededIn メソッドは、ReportFragment がまだ追加されていない場合にのみ二回目の追加を行います。

前述の通り、ProcessLifecycleOwnerInitializer は ContentProvider であり、ContentProvider が作成されるときに対応するプロセスの作成に伴って起動します。ActivityThread の main メソッドから ContentProvider の起動プロセスを確認し、Android ソースコードを確認するためのツール AndroidXRef をお勧めします。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。