fragment-ktx:1.2.5 で <fragment> を使うと FragmentContainerView を使うようにメッセージがでます。
このメッセージに従って FragmentContainerView に変えたとして、大体は問題ないと思いますが、問題が起こる場合もあります。
<fragment> と FragmentContainerView で Fragment のライフサイクルメソッドの呼ばれる順番を確認してみます。
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val f = supportFragmentManager
.findFragmentById(R.id.mainFragment) as MainFragment
Log.d("MainActivity", "onCreate : ${f.view}")
}
}
<?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainFragment"
android:name="yanzm.sample.myapplication.MainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
class MainFragment : Fragment() {
override fun onAttach(context: Context) {
super.onAttach(context)
Log.d("MainFragment", "onAttach")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("MainFragment", "onCreate")
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
Log.d("MainFragment", "onCreateView")
return View(inflater.context)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
Log.d("MainFragment", "onActivityCreated")
}
override fun onStart() {
super.onStart()
Log.d("MainFragment", "onStart")
}
override fun onResume() {
super.onResume()
Log.d("MainFragment", "onResume")
}
}
↑ の <fragment> の場合のコードを実行すると次のようになります。
D/MainFragment: onAttach
D/MainFragment: onCreate
D/MainFragment: onCreateView
D/MainActivity: onCreate : android.view.View{7009652 V.ED..... ......I. 0,0-0,0 #7f0800ca app:id/mainFragment}
D/MainFragment: onActivityCreated
D/MainFragment: onStart
D/MainFragment: onResume
Fragment の onAttach(), onCreate(), onCreateView() が呼ばれた後に Activity の onCreate() が呼ばれています。そのため、Activity の onCreate() で Fragment の View にアクセスすると null ではありません。
では FragmentContainerView に変えて見てみましょう。タグ以外は変更なしです。
<?xml version="1.0" encoding="utf-8"?>
<androidx.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/mainFragment"
android:name="yanzm.sample.myapplication.MainFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />
D/MainFragment: onAttach
D/MainFragment: onCreate
D/MainActivity: onCreate : null
D/MainFragment: onCreateView
D/MainFragment: onActivityCreated
D/MainFragment: onStart
D/MainFragment: onResume
なんと Fragment の onCreateView() の呼ばれるタイミングが変わっています。 Activity の onCreate() の後に呼ばれるように変わってしまいました。そのため Activity の onCreate() で Fragment の View にアクセスすると null になっています。
Activity の onCreate() の時点で Fragment の onCreateView() がすでに呼ばれている前提の処理だと、FragmentContainerView に変更したときに意図しない動きになってしまうので注意が必要です。