1

I have a code like this:

    private val appViewModel: AppViewModel by activityViewModels()
    private lateinit var user: User

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

        // This sets the variable user to the value collected from a StateFlow from appViewmodel 
        lifecycleScope.launchWhenCreated {
            appViewModel.user.collect { flowUser -> user = flowUser }
        }
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        
        // This method utilizes the lateinit user variable
        lifecycleScope.launchWhenStarted {
            doThingWithUser()
        }

        return binding?.root
    }

Since the value of StateFlow persists even after being collected, after the screen rotates the first lifecycleScope.launchWhenCreated gets called, collects the flowUser from the flow again, assigns it to the lateinit user variable, and doThingWithUser gets called later and everything works fine.

But after two or more rotations, this stops being the case, for some reason user doesn't get initialized, doThingWithUser gets called and the app crashes with kotlin.UninitializedPropertyAccessException.

What am I doing wrong? Does the value from StateFlow vanishes after two collections/screen rotations? Something happens with the actual flow inside the ViewModel? Something happens with the onCreate and onCreateView methods? Or does launchWhenStarted and launchWhenCreated behave differently after two rotations?

Thanks.

jpegoraro
  • 315
  • 2
  • 10

1 Answers1

0

I found out what the problem was. Apparently the Navigation Component messes with the order of the fragment's lifecycles, as seen here.

So when the screen rotated, due to the backstack order, the Navigation was creating another fragment that also interacts with the StateFlow of the ViewModel before the current Fragment. So, the other fragment onCreate method was sending something else to the flow, and therefore messing my current fragment collection.

The solution is to either make the flow collection independent of the fragment lifecycle, or change the collection in either one of the trouble fragments.

jpegoraro
  • 315
  • 2
  • 10