AndroidX以前
今までバックキーの制御と言えば、例えば以下のように Activity#onBackPressed()
でゴニョゴニョしていました。
override fun onBackPressed() { // バックキーイベントでFragmentで何かしたいとき val fragment = supportFragmentManager.findFragmentByTag("HogeFragment") fragment?.something() // スタックに積んだFragmentを1個前に戻したいとき if (supportFragmentManager.backStackEntryCount > 0) { supportFragmentManager.popBackStack() } else { super.onBackPressed() }
BackStackとかはまだいいですけど、Fragment側の処理をcallしたいときなどはActivityに特定のFragmentの依存が入ってしまって、残念な気持ちになっていました。
AndroidX以降
AndroidXで提供されているActivityには、Version 1.0.0-alpha01で Activity#addOnBackPressedCallback ()
というメソッドが追加され、 OnBackPressedCallback
インターフェース経由でバックキーのイベントを受けられるようになってました。
つまりFragment内にバックキー制御のロジックを閉じ込めることが出来るということです。控えめに言って最高です。
こんな感じで書くことが出来ました。
... import androidx.activity.OnBackPressedCallback import androidx.fragment.app.Fragment ... class MyFragment : Fragment() { private val callback = object : OnBackPressedCallback { override fun handleOnBackPressed(): Boolean { return if (isHoge) { something() true } else { false } } } override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) activity?.addOnBackPressedCallback(callback) ... } override fun onDestroy() { super.onDestroy() activity?.removeOnBackPressedCallback(callback) }
これだけでも嬉しいですが、リファレンスを見るとArchitecture ComponentのLifecycleにも対応していました。
つまり先程のサンプルコードは、以下のように書けます。
... import androidx.activity.OnBackPressedCallback import androidx.fragment.app.Fragment ... class MyFragment : Fragment() { override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) activity?.addOnBackPressedCallback(this, object : OnBackPressedCallback { override fun handleOnBackPressed(): Boolean { return if (isHoge) { something() true } else { false } } }) ... }
これでaddしたcallbackの開放を気にする必要が無くなりました。コード量も減るし、読みやすいです。 (OnBackPressedCallbackはJavaで実装されているのでSAM変換も可能ですし、実際にはさらにコード量は減らせます。)
これを発見したときにAndroidXに移行して良かったなと、心の底から思いました。AndroidX最高です。