セッションとかであー完全に理解したってなって10分後ぐらいに忘れるのでメモしておきます。
なにか必要なポイントとかが抜けていたり間違っているポイントがあれば教えてください。
ティラミス API Level 33 未満
1行まとめ: ActivityのonBackPressedを受け取ってcallbackに流す
参考コード
* 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()が呼ばれる
@Override
@MainThread
@CallSuper
@Deprecated
public void onBackPressed() {
mOnBackPressedDispatcher.onBackPressed();
}
最後のenableになっているcallbackを探して呼び出す。
誰にもハンドリングされなかったらOnBackPressedDispatcherに渡されているfallbackOnBackPressed()を呼び出す
@MainThread
fun onBackPressed() {
val callback = onBackPressedCallbacks.lastOrNull {
it.isEnabled
}
inProgressCallback = null
if (callback != null) {
callback.handleOnBackPressed()
return
}
fallbackOnBackPressed?.run()
}
ティラミス API 33
1行まとめ: OnBackInvokedDispatcherから受け取ってcallbackに流す
ActivityでmOnBackPressedDispatcher.setOnBackInvokedDispatcherで渡す。
@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)
);
}
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から呼ばれるメソッド
@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
}
}
}
@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
などが呼び出されるようになるみたいです。
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() }
}
}
}
@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が渡ってくるところが違いそう
@MainThread
private fun onBackStarted(backEvent: BackEventCompat) {
val callback = onBackPressedCallbacks.lastOrNull {
it.isEnabled
}
inProgressCallback = callback
if (callback != null) {
callback.handleOnBackStarted(backEvent)
return
}
}