blog

ライフサイクルのソースコードを読む

ライフサイクルの概要\nライフサイクルは、アクティビティとフラグメントのライフサイクルの変化を感知するために使用できます。\n\nonResume:再生を再開します。\nonPause:再生を一時停止...

May 10, 2020 · 8 min. read
シェア

ライフサイクルの概要

ライフサイクルは、アクティビティやフラグメントのライフサイクルの変化を感知するために使用できます。

例:ビデオ再生にライフサイクルを使用する場合、関連するライフサイクルの間、一般にプレーヤで以下の処理が実行されます。

  • onResume:再生の再開
  • onPause:再生の一時停止
  • onDestory:プレイヤーをデストロイ

このロジックがページとは関係のないアクティビティやフラグメントに配置されている場合、これらのメソッドが使用される場所ごとに何度も何度も追加し続ける必要があり、プログラム開発にとって良いことではありません。ライフサイクルの助けを借りて、このロジックのこの部分の実装のパブリック部分を抽出することができ、これらのロジックを実現するためのコードの行にすることができます。

ライフサイクルの利用

アクティビティやフラグメントのライフサイクルの変化を検知したい場合は、LifecycleObserverインターフェイスを実装し、対応するメソッドにライフサイクルイベントアノテーションを追加する必要があります。コード例を以下に示します:

class BasicLifecycleObserver() : LifecycleObserver {
 private var listener:ILifecycleListener? = null
 constructor(listener: ILifecycleListener):this(){
 this.listener = listener
 }
 fun setLifecycleListener(listener: ILifecycleListener){
 this.listener = listener
 }
 @OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
 fun onCreate() {
 listener?.lifecycleCreate()
 }
 @OnLifecycleEvent(Lifecycle.Event.ON_START)
 fun onStart() {
 listener?.lifecycleStart()
 }
 @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
 fun onResume() {
 listener?.lifecycleResume()
 }
 @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
 fun onPause() {
 listener?.lifecyclePause()
 }
 @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
 fun onStop() {
 listener?.lifecycleStop()
 }
 @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
 fun onDestroy() {
 listener?.lifecycleDestroy()
 }
}

では、このオブザーバーをどのように使うのでしょうか?Google はアクティビティとフラグメントの両方で LifecycleOwner インターフェイスを実装しています。

public interface LifecycleOwner {
 /**
 * Returns the Lifecycle of the provider.
 *
 * @return The lifecycle of the provider.
 */
 @NonNull
 Lifecycle getLifecycle();
}

getLifecycle メソッドを直接呼び出して LifeCycle オブジェクトを取得し、addObserver を使用して対応するリスナーを追加します。

ライフサイクル・ソースコード解析

上のコードからわかるように、ライフサイクルはとてもシンプルに使えます。ソースコードを見てみてください。

private LifecycleRegistry mLifecycleRegistry = new LifecycleRegistry(this);

LifecycleRegistryが弱い参照でアクティビティ・オブジェクトを保持していることがわかります。これにより、アクティビティが再要求されたときにメモリリークが発生することはありません。

LifecycleRegistryのaddObserverメソッドを見てみましょう。

public void addObserver(@NonNull LifecycleObserver observer) {
 State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
 ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
 ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);
 if (previous != null) {
 return;
 }
 LifecycleOwner lifecycleOwner = mLifecycleOwner.get();
 if (lifecycleOwner == null) {
 // it is null we should be destroyed. Fallback quickly
 return;
 }
 boolean isReentrance = mAddingObserverCounter != 0 || mHandlingEvent;
 State targetState = calculateTargetState(observer);
 mAddingObserverCounter++;
 while ((statefulObserver.mState.compareTo(targetState) < 0
 && mObserverMap.contains(observer))) {
 pushParentState(statefulObserver.mState);
 statefulObserver.dispatchEvent(lifecycleOwner, upEvent(statefulObserver.mState));
 popParentState();
 // mState / subling may have been changed recalculate
 targetState = calculateTargetState(observer);
 }
 if (!isReentrance) {
 // we do sync only on the top level.
 sync();
 }
 mAddingObserverCounter--;
 }

ロジックは、おおよそ次のとおりです。最初にリスナーを追加するかどうかを決定し、それが追加されている場合は、直接終了し、ライフサイクルの状態を認識するために、現在の必要性に基づいて追加されていない場合は、順番に配布され、それを簡単に言うと、リスナーを追加するには、アクティビティでonResumeと仮定され、それはonCreate、onStart、onResumeが受信されます。コールバック。

実験中。

アクティビティ

class LifecycleActivity : AppCompatActivity() {
 private val TAG = LifecycleActivity::class.java.simpleName
 override fun onCreate(savedInstanceState: Bundle?) {
 super.onCreate(savedInstanceState)
 setContentView(R.layout.activity_lifecycle)
 }
 override fun onResume() {
 super.onResume()
 val observer = BasicLifecycleObserver(object :ILifecycleListener{
 override fun lifecycleCreate() {
 Log.d(TAG,"lifecycleCreate")
 }
 override fun lifecycleStart() {
 Log.d(TAG,"lifecycleStart")
 }
 override fun lifecycleResume() {
 Log.d(TAG,"lifecycleResume")
 }
 override fun lifecyclePause() {
 Log.d(TAG,"lifecyclePause")
 }
 override fun lifecycleStop() {
 Log.d(TAG,"lifecycleStop")
 }
 override fun lifecycleDestroy() {
 Log.d(TAG,"lifecycleDestroy")
 }
 })
 lifecycle.addObserver(observer)
 }
}
interface ILifecycleListener {
 fun lifecycleCreate()
 fun lifecycleStart()
 fun lifecycleResume()
 fun lifecyclePause()
 fun lifecycleStop()
 fun lifecycleDestroy()
}

このアクティビティを開くと、ログで確認できます:

オブザーバを追加するコードから、LifecycleRegistyが直接オブザーバを追加するのではなく、ObserverWithStateオブジェクトを追加することで間接的にオブザーバを追加することがわかります。

 State initialState = mState == DESTROYED ? DESTROYED : INITIALIZED;
 ObserverWithState statefulObserver = new ObserverWithState(observer, initialState);
 ObserverWithState previous = mObserverMap.putIfAbsent(observer, statefulObserver);

ObserverWithStateクラスの実装はとてもシンプルです。

static class ObserverWithState {
 State mState;
 LifecycleEventObserver mLifecycleObserver;
 ObserverWithState(LifecycleObserver observer, State initialState) {
 //LifecycleObserverオブジェクトを外部のLifecycleEventObserver
 mLifecycleObserver = Lifecycling.lifecycleEventObserver(observer);
 mState = initialState;
 }
 void dispatchEvent(LifecycleOwner owner, Event event) {
 State newState = getStateAfter(event);
 mState = min(mState, newState);
 mLifecycleObserver.onStateChanged(owner, event);
 mState = newState;
 }
 }

システムがLifecycleEventObserverをどのように構築するか、大まかに見てみましょう。

static LifecycleEventObserver lifecycleEventObserver(Object object) {
 boolean isLifecycleEventObserver = object instanceof LifecycleEventObserver;
 boolean isFullLifecycleObserver = object instanceof FullLifecycleObserver;
 if (isLifecycleEventObserver && isFullLifecycleObserver) {
 return new FullLifecycleObserverAdapter((FullLifecycleObserver) object,
 (LifecycleEventObserver) object);
 }
 if (isFullLifecycleObserver) {
 return new FullLifecycleObserverAdapter((FullLifecycleObserver) object, null);
 }
 if (isLifecycleEventObserver) {
 return (LifecycleEventObserver) object;
 }
 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);
 }

転送されたオブジェクトが LifecycleEventObserver インタフェースのみを実装している場合は、現在のオブジェクト自身を返します。FullLifecycleObserver を実装している場合は、FullLifecycleObserverAdapter を返します。を使用して現在のクラスの情報を保存し、アダプタ変換によって対応するメソッドにコールバックします。

ここまで、アクティビティのライフサイクルの変化を聞く方法について見てきましたが、アクティビティのライフサイクルの変化はどのようにして始まるのでしょうか?これを調べるには、明らかにアクティビティに行く必要があります。FragmentActivityでは、LifecycleRelatedメソッドの場所にLifecycleRegistry#handleLifecycleEventへの呼び出しがたくさんあることがわかります。このことから、LifecycleObserverがどのようにライフサイクルを感知しているかがわかります。

カスタムLifecycleOwnerの実装

カスタムクラスがあり、それをLifecycleOwnerにしたい場合、LifecycleRegistryクラスを使用することができますが、次のコード例に示すように、そのクラスにイベントを転送する必要があります。

public class MyActivity extends Activity implements LifecycleOwner {
 private LifecycleRegistry lifecycleRegistry;
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 lifecycleRegistry = new LifecycleRegistry(this);
 lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
 }
 @Override
 public void onStart() {
 super.onStart();
 lifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
 }
 @NonNull
 @Override
 public Lifecycle getLifecycle() {
 return lifecycleRegistry;
 }
 }
 

概要

  1. ライフサイクルを検知するには、LifecycleObserverインターフェイスを実装し、LifecycleOwnerからライフサイクルを取得することで、ライフサイクルをリッスンすることができます。

  2. デザインパターンの観点からは、Lifecycleは典型的なオブザーバーパターンであり、ライフサイクルを持つオブジェクトは、その状態が変化するとオブザーバーに通知します。

  3. Lifecycleでは、アダプタパターンを使用して、対応するメソッドがコールバックされるオブザーバを適応変換によって適応させることで、リスナーを追加します。例えば

    class FullLifecycleObserverAdapter implements LifecycleEventObserver {
     private final FullLifecycleObserver mFullLifecycleObserver;
     private final LifecycleEventObserver mLifecycleEventObserver;
     FullLifecycleObserverAdapter(FullLifecycleObserver fullLifecycleObserver,
     LifecycleEventObserver lifecycleEventObserver) {
     mFullLifecycleObserver = fullLifecycleObserver;
     mLifecycleEventObserver = lifecycleEventObserver;
     }
     @Override
     public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
     switch (event) {
     case ON_CREATE:
     mFullLifecycleObserver.onCreate(source);
     break;
     case ON_START:
     mFullLifecycleObserver.onStart(source);
     break;
     case ON_RESUME:
     mFullLifecycleObserver.onResume(source);
     break;
     case ON_PAUSE:
     mFullLifecycleObserver.onPause(source);
     break;
     case ON_STOP:
     mFullLifecycleObserver.onStop(source);
     break;
     case ON_DESTROY:
     mFullLifecycleObserver.onDestroy(source);
     break;
     case ON_ANY:
     throw new IllegalArgumentException("ON_ANY must not been send by anybody");
     }
     if (mLifecycleEventObserver != null) {
     mLifecycleEventObserver.onStateChanged(source, event);
     }
     }
    }
    

    関連するライフサイクルメソッドに対応するコールバックがここで直接定義されず、適応変換によって処理される理由も、今のところ理解できません。将来の拡張のためでしょうか?

Read next

iOS開発ツール - コード生成、重複ソートコードのコピー

FlyCodingはAppleのプラグイン機構を使って書かれたXcodeプラグインで、最新のXcode上で動作し、フロントエンドでEmmetに似た機能を提供します。Emmetのようなフロントエンドの機能を提供します。 特にUIをたくさん書くとき、繰り返しコーディングするときなど、特別な構文で欲しいSwfit/Objective-Cのコードを素早く生成することができます...

May 10, 2020 · 13 min read