画面遷移が得意なiOSでも画面間のデータの受け渡しは千差万別でした。いわんやAndroidもfragmentは歴史が浅いのか四苦八苦しました。
調べたところ、3つほど方法がみつかりました。
いったいどれを使うのが良いのか検討してみました。かなり独断と偏見なので、詳細は今後調べる必要があるかと思います。
ActivityModels
kotlinの開発案件で使われているソースを見かけます。
ViewModelを共有できるので便利ですが、その名の通りActivityを取得した共有であることに注意が必要です。
ViewModelを共有するので、任意のデータを共有するだけでなく、ロジックも共有したい場合に便利そうです。
Fragment KTXと呼ばれる拡張モジュールによって簡単に提供されてるので、次のように宣言するだけで共有されるためわかりやすいです。
1 2 3 |
class Fragment : Fragment() { private val viewModel : ViewModel by activityViewModels() } |
setFragmentResult
FragmentManagerによるFragment間のデータの受け渡しを提供する機能のようです。
あるフラグメントの結果データを使いたい場合に便利かと思います。
ただ複数データの場合Bundleのため、変換実装が必要になることが想像しえます。
こちらもFragment KTXと呼ばれる拡張モジュールによって提供されています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<meta charset="utf-8">// 受け側Fragment override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setResultListener("Result") { key, bundle -> val resultValue = bundle.getString("key") } } // 送り側Fragment <meta charset="utf-8">override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) button.setOnClickListener { setResult("<meta charset="utf-8">Result", bundleOf("key" to "result value")) } } |
BackStackEntry
NavControllerに提供されるデータ受け渡しの機能のため、NavControllerを使っている場合はこちらを使うことになるかと思います。
currentBackStackEntryとpreviousBackStackEntryを使います。
使い方はsetFragmentResultsと似てますが、Mapで返却できたのでBundleよりは扱いやすいかなと感じました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<meta charset="utf-8">// 受け側Fragment override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) findNavController().currentBackStackEntry?.savedStateHandle?.getLiveData<String>("result") ?.observe(viewLifecycleOwner) { } } // 送り側Fragment <meta charset="utf-8">override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) button.setOnClickListener { findNavController().previousBackStackEntry?.savedStateHandle?.set("result", "ABC") findNavController().popBackStack() } } |
データを1回だけ受け取る場合は受け取り後にremoveする必要があります。
結論
Fragment間でロジックを共有する場合はactivityModelsを利用して、データの受け取りだけであればNavControllerを使っていればBackStackEntry、使っていなければFragmentManagerのsetFragmentResultを使えばよいのかなといまいまは考えております。
何かご助言いただけれる場合はご連絡いただけますと幸いです。