androidkotlinandroid-fragmentslayout-inflater

Android - Activity and Fragment initialization


I have an application composed of one activity and several fragments, as recommanded by Google. Other details here. I would like to keep a menu still and to switch my fragments in the container in the center.

activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.google.android.material.appbar.AppBarLayout
        android:someProperties="propertiesValues">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:someProperties="propertiesValues" />

    </com.google.android.material.appbar.AppBarLayout>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:name="androidx.navigation.fragment.NavHostFragment"
        app:navGraph="@navigation/navigation_map"
        />

    <com.google.android.material.floatingactionbutton.FloatingActionButton
        android:id="@+id/fab"
        android:someProperties="propertiesValues" />

    </androidx.coordinatorlayout.widget.CoordinatorLayout>

activity_main.xml

MainActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        println("Activity creation")
        val binding = ActivityMainBinding.inflate(layoutInflater)
        println("Activity creation part 2")
        setContentView(binding.root)
        setSupportActionBar(binding.toolbar)

        User.initSharedPref(this)
    }

Fragment

private lateinit var mylist: MutableList<String>>
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    println("Fragment creation")

    mylist = User.loadScenarioList()
}

User

object User
{
  private lateinit var sharedPref : SharedPreferences

  fun initSharedPref(context: Context){
    sharedPref = context.getSharedPreferences("JeuDePisteKtPreferenceFileKey",Context.MODE_PRIVATE)
  }

  fun loadList(): MutableList<String>> {
      val json = sharedPref.getString(KEY_LIST, "") ?: ""
      if (json == "") return mutableListOf()
      return Json.decodeFromString(json)
  }

}

Problem encountered

When i start the activity, it initialize a variable sharedPref as shown in code.

But when in fragment onCreate i use this variable (mylist = User.loadScenarioList()), the binding line in activity fail with Binary XML file line #31: Error inflating class androidx.fragment.app.FragmentContainerView as shown in logcat below

Logcat & error

Here is the full logcat, we can see the the second sout is missing, but with no error thrown at this point.

logcat


Solution

  • The problem here came from the order of creation call

    We can see it in the corrected code logcat logcat

    The activity onCreate is called first, but the first inflate call the fragment OnCreate, before resuming the activity OnCreate.

    So every variable used in the fragment onCreate should be initialized before inflate call