OnBackPressedDispatcher周りをシーケンス図にまとめる

セッションとかであー完全に理解したってなって10分後ぐらいに忘れるのでメモしておきます。
なにか必要なポイントとかが抜けていたり間違っているポイントがあれば教えてください。


# ティラミス API Level 33 未満

1行まとめ: ActivityのonBackPressedを受け取ってcallbackに流す

```mermaid
sequenceDiagram
    participant System
    participant ComponentActivity
    participant OnBackPressedDispatcher
    participant OnBackPressedCallback
    ComponentActivity->>OnBackPressedDispatcher: addCallback(callback)
    OnBackPressedDispatcher->>OnBackPressedDispatcher: callbackを保持する
    System->>ComponentActivity: onBackPressed()
    ComponentActivity->>OnBackPressedDispatcher: onBackPressed()
    OnBackPressedDispatcher->>OnBackPressedCallback: handleOnBackPressed()
```

### 参考コード

```kotlin
 * class FormEntryFragment : Fragment() {
 *   override fun onAttach(context: Context) {
 *     super.onAttach(context)
 *     val callback = object : OnBackPressedCallback(
 *       true // default to enabled
 *     ) {
 *       override fun handleOnBackPressed() {
 *         showAreYouSureDialog()
 *       }
 *     }
 *     requireActivity().onBackPressedDispatcher.addCallback(
 *       this, // LifecycleOwner
 *       callback
 *     )
 *   }
 * }
```

システムからonBackPressed()が呼ばれる

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:activity/activity/src/main/java/androidx/activity/ComponentActivity.java;l=699

```kotlin:ComponentActivity
    @Override
    @MainThread
    @CallSuper
    @Deprecated
    public void onBackPressed() {
        mOnBackPressedDispatcher.onBackPressed();
    }
```



**最後のenableになっているcallbackを探して呼び出す**。
誰にもハンドリングされなかったらOnBackPressedDispatcherに渡されているfallbackOnBackPressed()を呼び出す

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:activity/activity/src/main/java/androidx/activity/OnBackPressedDispatcher.kt;l=270

```kotlin:OnBackPressedDispatcher
    @MainThread
    fun onBackPressed() {
        val callback = onBackPressedCallbacks.lastOrNull {
            it.isEnabled
        }
        inProgressCallback = null
        if (callback != null) {
            callback.handleOnBackPressed()
            return
        }
        fallbackOnBackPressed?.run()
    }
```

# ティラミス API 33

1行まとめ: OnBackInvokedDispatcherから受け取ってcallbackに流す

```mermaid
sequenceDiagram
    participant System
    participant ComponentActivity
    participant OnBackPressedDispatcher
    participant OnBackPressedCallback
    OnBackPressedDispatcher->>OnBackPressedDispatcher: onBackInvokedCallbackを保持する
    ComponentActivity->>OnBackPressedDispatcher: setOnBackInvokedDispatcher
    ComponentActivity->>OnBackPressedDispatcher: addCallback(callback)
    OnBackPressedDispatcher->>OnBackPressedDispatcher: callbackを保持する
    OnBackPressedDispatcher->>OnBackInvokedDispatcher: onBackInvokedDispatcher.registerOnBackInvokedCallback(onBackInvokedCallback)
    System->>OnBackInvokedCallback: onBackPressed()
    OnBackInvokedCallback->>OnBackPressedDispatcher: onBackPressed()
    OnBackPressedDispatcher->>OnBackPressedCallback: handleOnBackPressed()
```

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:activity/activity/src/main/java/androidx/activity/ComponentActivity.java;l=370-382

ActivityでmOnBackPressedDispatcher.setOnBackInvokedDispatcherで渡す。

```java:ComponentActivity
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        // Restore the Saved State first so that it is available to
        // OnContextAvailableListener instances
        mSavedStateRegistryController.performRestore(savedInstanceState);
        mContextAwareHelper.dispatchOnContextAvailable(this);
        super.onCreate(savedInstanceState);
        ReportFragment.injectIfNeededIn(this);
        if (Build.VERSION.SDK_INT >= 33) {
            mOnBackPressedDispatcher.setOnBackInvokedDispatcher(
                    Api33Impl.getOnBackInvokedDispatcher(this)
            );
        }
```

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:activity/activity/src/main/java/androidx/activity/OnBackPressedDispatcher.kt;l=90

```kotlin:OnBackPressedDispatcher
    init {
        if (Build.VERSION.SDK_INT >= 33) {
            onBackInvokedCallback = if (Build.VERSION.SDK_INT >= 34) {
                Api34Impl.createOnBackAnimationCallback(
                    { backEvent -> onBackStarted(backEvent) },
                    { backEvent -> onBackProgressed(backEvent) },
                    { onBackPressed() },
                    { onBackCancelled() }
                )
            } else {
                // こっち
                Api33Impl.createOnBackInvokedCallback { onBackPressed() }
            }
        }
    }
```

registerCallbackから呼ばれるメソッド

```kotlin:OnBackPressedDispatcher
    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    private fun updateBackInvokedCallbackState(shouldBeRegistered: Boolean) {
        val dispatcher = invokedDispatcher
        val onBackInvokedCallback = onBackInvokedCallback
        if (dispatcher != null && onBackInvokedCallback != null) {
            if (shouldBeRegistered && !backInvokedCallbackRegistered) {
                Api33Impl.registerOnBackInvokedCallback(
                    dispatcher,
                    OnBackInvokedDispatcher.PRIORITY_DEFAULT,
                    onBackInvokedCallback
                )
                backInvokedCallbackRegistered = true
            } else if (!shouldBeRegistered && backInvokedCallbackRegistered) {
                Api33Impl.unregisterOnBackInvokedCallback(
                    dispatcher,
                    onBackInvokedCallback
                )
                backInvokedCallbackRegistered = false
            }
        }
    }
```

```kotlin
    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
    internal object Api33Impl {
        @DoNotInline
        fun registerOnBackInvokedCallback(
            dispatcher: Any,
            priority: Int,
            callback: Any
        ) {
            val onBackInvokedDispatcher = dispatcher as OnBackInvokedDispatcher
            val onBackInvokedCallback = callback as OnBackInvokedCallback
            onBackInvokedDispatcher.registerOnBackInvokedCallback(priority, onBackInvokedCallback)
        }

        @DoNotInline
        fun unregisterOnBackInvokedCallback(dispatcher: Any, callback: Any) {
            val onBackInvokedDispatcher = dispatcher as OnBackInvokedDispatcher
            val onBackInvokedCallback = callback as OnBackInvokedCallback
            onBackInvokedDispatcher.unregisterOnBackInvokedCallback(onBackInvokedCallback)
        }

        @DoNotInline
        fun createOnBackInvokedCallback(onBackInvoked: () -> Unit): OnBackInvokedCallback {
            return OnBackInvokedCallback { onBackInvoked() }
        }
    }
```

# API 34

1行まとめ: だいたい33と一緒っぽい。 ただ追加で`onBackStarted`や`onBackProgressed`などが呼び出されるようになるみたいです。


```mermaid
sequenceDiagram
    participant System
    participant ComponentActivity
    participant OnBackPressedDispatcher
    participant OnBackPressedCallback
    OnBackPressedDispatcher->>OnBackPressedDispatcher: onBackInvokedCallbackを保持する
    ComponentActivity->>OnBackPressedDispatcher: setOnBackInvokedDispatcher
    ComponentActivity->>OnBackPressedDispatcher: addCallback(callback)
    OnBackPressedDispatcher->>OnBackPressedDispatcher: callbackを保持する
    OnBackPressedDispatcher->>OnBackInvokedDispatcher: onBackInvokedDispatcher.registerOnBackInvokedCallback(onBackInvokedCallback)
    System->>OnBackInvokedCallback: onBackStarted()
    OnBackInvokedCallback->>OnBackPressedDispatcher: onBackStarted()
    OnBackPressedDispatcher->>OnBackPressedCallback: handleOnBackStarted(BackEventCompat)

    System->>OnBackInvokedCallback: onBackPressed()
    OnBackInvokedCallback->>OnBackPressedDispatcher: onBackPressed()
    OnBackPressedDispatcher->>OnBackPressedCallback: handleOnBackPressed()
```

https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:activity/activity/src/main/java/androidx/activity/OnBackPressedDispatcher.kt;l=126

```kotlin:OnBackPressedDispatcher
    init {
        if (Build.VERSION.SDK_INT >= 33) {
            onBackInvokedCallback = if (Build.VERSION.SDK_INT >= 34) {
                // こっち
                Api34Impl.createOnBackAnimationCallback(
                    { backEvent -> onBackStarted(backEvent) },
                    { backEvent -> onBackProgressed(backEvent) },
                    { onBackPressed() },
                    { onBackCancelled() }
                )
            } else {
                Api33Impl.createOnBackInvokedCallback { onBackPressed() }
            }
        }
    }
```



```kotlin

    @RequiresApi(34)
    internal object Api34Impl {
        @DoNotInline
        fun createOnBackAnimationCallback(
            onBackStarted: (backEvent: BackEventCompat) -> Unit,
            onBackProgressed: (backEvent: BackEventCompat) -> Unit,
            onBackInvoked: () -> Unit,
            onBackCancelled: () -> Unit
        ): OnBackInvokedCallback {
            return object : OnBackAnimationCallback {
                override fun onBackStarted(backEvent: BackEvent) {
                    onBackStarted(BackEventCompat(backEvent))
                }

                override fun onBackProgressed(backEvent: BackEvent) {
                    onBackProgressed(BackEventCompat(backEvent))
                }

                override fun onBackInvoked() {
                    onBackInvoked()
                }

                override fun onBackCancelled() {
                    onBackCancelled()
                }
            }
        }
    }
```

started周りもだいたいonBackPressedと同じ仕組みで動くが、引数にBackEventCompatが渡ってくるところが違いそう

```kotlin
    @MainThread
    private fun onBackStarted(backEvent: BackEventCompat) {
        val callback = onBackPressedCallbacks.lastOrNull {
            it.isEnabled
        }
        inProgressCallback = callback
        if (callback != null) {
            callback.handleOnBackStarted(backEvent)
            return
        }
    }

```