Search code examples
androidandroid-lifecycleandroid-viewmodel

How to restore the menu state on configuration change


I have 2 menu items (filter button and search button) that allow to filter or search within a list. When a list item is selected, it is given to the view throught the viewModel's LiveData called listItemSelected, when this happen, we move from the ListFragment to the DetailFragment and hide the 2 buttons from the menu, as they aren't relevent here.

My problem is on configuration change, for example on screen rotation, the old activity is destroyed, and the new Activity.onCreate() function is called before onCreateOptionsMenu(), so I don't know how can I set back the menu state properly.

Simplified code sample below, right now it just crash on filterMenuItem.isVisible = it == null because filterMenuItem is not initialized at this point.

class MyActivity : AppCompatActivity() {

    private lateinit var viewModel: MyViewModel
    private lateinit var filterMenuItem: MenuItem
    private lateinit var searchMenuItem: MenuItem

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewModel = getViewModel { injector.myViewModel }
        viewModel.listItemSelected.observe(this, Observer {
            filterMenuItem.isVisible = it == null
            searchMenuItem.isVisible = it == null
        })
    }

    override fun onCreateOptionsMenu(menu: Menu?): Boolean {
        menuInflater.inflate(R.menu.main_menu, menu)

        menu!!.apply {
            filterMenuItem = findItem(R.id.main_menu_filter)
            searchMenuItem = findItem(R.id.main_menu_search)
        }

        return true
    }


Solution

  • How about observing data after you initialized the MenuItem's:

    class MyActivity : AppCompatActivity() {
    
        private lateinit var viewModel: MyViewModel
        private lateinit var filterMenuItem: MenuItem
        private lateinit var searchMenuItem: MenuItem
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            viewModel = getViewModel { injector.myViewModel }
        }
    
        override fun onCreateOptionsMenu(menu: Menu?): Boolean {
            menuInflater.inflate(R.menu.main_menu, menu)
    
            menu!!.apply {
                filterMenuItem = findItem(R.id.main_menu_filter)
                searchMenuItem = findItem(R.id.main_menu_search)
            }
    
            // observe after the menu items are initialized
            viewModel.listItemSelected.observe(this, Observer {
                filterMenuItem.isVisible = it == null
                searchMenuItem.isVisible = it == null
            })
    
            return true
        }
    }