简体   繁体   中英

savedInstanceState not restoring Fragment properly

Why is it that my fragment returns a blank screen whenever I use savedInstanceState with it? I've already included the relevant savedInstanceState code in my activity, but the associated fragment still doesn't appear at all.

class MyActivity : AppCompatActivity() {
    private var mCurrentValue: Boolean = false

    private var mTwoPane: Boolean = false

    private var activityRecreated: Boolean = false

    override fun onCreate(savedInstanceState: Bundle?) {
        val mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
        mCurrentValue = mSharedPreferences.getBoolean("preference_a", false)
        when {
            mCurrentValue -> setTheme(R.style.MyDarkTheme)
            else -> setTheme(R.style.MyLightTheme)
        }

        super.onCreate(savedInstanceState)

        activityRecreated = savedInstanceState != null

        setContentView(R.layout.md)
    }

    override fun onStart() {
        super.onStart()

        setContentView(R.layout.md)

        mTwoPane = findViewById<View>(R.id.detail_container) != null

        val mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(this)
        val mNewValue = mSharedPreferences.getBoolean("preference_a", false)
        when {
            mCurrentValue != mNewValue -> recreate()
        }

        val mToolbar = findViewById<Toolbar>(R.id.my_toolbar)
        setSupportActionBar(mToolbar) 

        if (activityRecreated) {
            val newFragment = MyFragment()
            val transaction = supportFragmentManager.beginTransaction()
            transaction.replace(R.id.master_container, newFragment)
            transaction.commit()
        }
    }
}

There are a few problems here.

  1. You should be setting your content view in onCreate() , not onStart() . onStart() can be invoked multiple times for the same Activity instance. For instance, if you start your Activity , press the Home button, and then resume your app, you'll go through onPause() , onStop() , then onStart() , onResume() . You only need to initialize your view when the Activity is created.

  2. Your logic to display the Fragment only executes if the Activity is being recreated . I think you likely meant the inverse. You could simply change that to be if (!activityRecreated) but I would instead suggest cleaning this up by moving your view initialization entirely into onCreate() like so, and only checking if the theme state has changed in onStart() :


class MyActivity : AppCompatActivity() {
    private val useDarkTheme: Boolean = false
    private var twoPane: Boolean = false

    override fun onCreate(savedInstanceState: Bundle?) {
        useDarkTheme = shouldUseDarkTheme()
        setTheme(if (useDarkTheme) R.style.MyDarkTheme else R.style.MyLightTheme)

        super.onCreate(savedInstanceState)
        setContentView(R.layout.md)

        // savedInstanceState will be null only the first time the Activity is created
        if (savedInstanceState == null) {
            supportFragmentManager.beginTransaction()
                .replace(R.id.master_container, MyFragment())
                .commit()
        }

        twoPane = findViewById<View>(R.id.detail_container) != null
        setSupportActionBar(findViewById(R.id.my_toolbar))
    }

    override fun onStart() {
        super.onStart()

        if (useDarkTheme != shouldUseDarkTheme()) {
            recreate()
        }
    }

    private fun shouldUseDarkTheme(): Boolean = 
        PreferenceManager.getDefaultSharedPreferences(this).getBoolean("preference_a", false)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM