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?
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.