Home > Mobile >  Cant add fragment inside of lifecycleScope coroutine
Cant add fragment inside of lifecycleScope coroutine

Time:02-15

I am using lifecycleScope.launch in my activity's onCreate to collect a flow but I also am trying to attach a fragment inside the scope but I just get a black screen when trying to do this like it never gets attached.

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

    setContentView(R.layout.main_activity)

    lifecycleScope.launch {
        _viewModel.listenForScheduleChanges().flowWithLifecycle(lifecycle, Lifecycle.State.STARTED).collect {

        }

        _viewModel.loadConfig() // suspend method that loads information

        _webFragment = WebFragment().apply {
            arguments = Bundle().apply {
                putParcelable("config", _viewModel.config)
            }
        }

        supportFragmentManager.beginTransaction()
            .replace(R.id.contentPanel, _webFragment!!)
            .commit()
    }

}

If I dont use lifecycleScope and implement CoroutineScope in my activity with that coroutine scope the fragment attaches fine

class MainActivity : AppCompatActivity(), CoroutineScope{

    private val job = SupervisorJob()
    override val coroutineContext: CoroutineContext
        get() = Dispatchers.Main   job

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

        setContentView(R.layout.main_activity)

        lifecycleScope.launch {
            _viewModel.listenForScheduleChanges().flowWithLifecycle(lifecycle, Lifecycle.State.STARTED).collect {

            }
        }

        launch {
            _viewModel.loadConfig() // suspend method that loads information

            _webFragment = WebFragment().apply {
                arguments = Bundle().apply {
                    putParcelable("config", _viewModel.config)
                }
            }

            supportFragmentManager.beginTransaction()
                .replace(R.id.contentPanel, _webFragment!!)
                .commit()
        }

    }

}

I dont understand why, both appear to be using the same context with the Dispatcher as Main.

Can someone provide insight here?

CodePudding user response:

Separate the code that collects data from flow to another coroutine scope your problem will be solved:

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

    setContentView(R.layout.main_activity)

    lifecycleScope.launch {
            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
                _viewModel.listenForScheduleChanges().collect {

                }
            }
    }

    lifecycleScope.launch {
       
        _viewModel.loadConfig() // suspend method that loads information

        _webFragment = WebFragment().apply {
            arguments = Bundle().apply {
                putParcelable("config", _viewModel.config)
            }
        }

        supportFragmentManager.beginTransaction()
            .replace(R.id.contentPanel, _webFragment!!)
            .commit()
    }

}

the issue is that when you collect a flow in this way it blocks the whole scope and other codes in the scope are not running.

  • Related