androidx.fragment:fragment:1.3.0-alpha04
から新しく setFragmentResult / setFragmentResultListener
が追加され、setTargetFragment
がdeprecatedになりました。
おそらく多くの呼び出し元に通知を送るDialogFragment
では、setTargetFragment
を使ってListenerなどで実装していたのではないでしょうか。
class MyDialogFragment : DialogFragment() {
companion object {
private const val REQUEST_CODE = 100
fun show(target: Fragment) =
newInstance().run {
setTargetFragment(target, REQUEST_CODE)
show(target.requireFragmentManager(), "MyDialogFragment")
}
private fun newInstance() = MyDialogFragment()
}
private lateinit var listener: MyListener
override fun onAttach(context: Context?) {
super.onAttach(context)
listener = targetFragment as? MyListener
?: throw IllegalArgumentException("This targetFragment is not `MyListener`")
}
・・・
・・・
・・・
interface MyListener {
fun onClickHoge()
fun onDismiss()
}
}
だいたいこんな感じかと思うんですが、
もちろんsetTargetFragment
もrequireFragmentManager
も使えないので、
以下のような感じにすると、これまでの使用感をあまり変えずに、実装できるのではないでしょうか。
class MyDialogFragment : DialogFragment() {
companion object {
private const val REQUEST_KEY = "request_key_my_dialog"
private const val RESULT_KEY_HOGE = "result_key_hoge_my_dialog"
private const val RESULT_KEY_DISMISS = "result_key_dismiss_my_dialog"
fun show(
target: Fragment,
onClickHoge: (() -> Unit)? = null,
onDismiss: (() -> Unit)? = null
) {
newInstance().run {
target
.childFragmentManager
.setFragmentResultListener(REQUEST_KEY, target.viewLifecycleOwner) { requestKey, bundle ->
if (requestKey != REQUEST_KEY) return@setFragmentResultListener
when {
bundle.containsKey(RESULT_KEY_HOGE) -> onClickHoge?.invoke()
bundle.containsKey(RESULT_KEY_DISMISS) -> onDismiss?.invoke()
}
}
show(target.childFragmentManager, "MyDialogFragment")
}
}
private fun newInstance() = MyDialogFragment()
}
まず、setFragmentResultListener
にすることで、カスタムリスナーは必要なくなり、
onAttach
での処理も全て必要なくなります。
ちなみに結果を通知する際は、例に倣って以下のように行います
// 通知したい場所で
setFragmentResult(REQUEST_KEY, bundleOf(RESULT_KEY_DISMISS to ""))
従来のDialogFragmentを使用する場合は、
// Fragmentで呼ぶ場合を想定
MyDialog.show(this)
こんな感じでshowして、通知に関しては、Fragmentにリスナーを実装していたと思いますが、
MyDialog.show(
target = this,
onClickHoge = {
// Hogeの処理
},
onDismiss = {
// Dismissの処理
}
)
といった感じで、ラムダを使用して、カスタムリスナーを使用しなくても、
通知を実装することができ、とてもシンプルになります。
いかがでしょうか?
何かもう少しこうしたら良いなど、ご意見あればお願いいたします。