SharedFlow is not getting collected in previous fragment when another fragment is added on top

65 Views Asked by At

Here is my MainActivity :

class MainActivity : AppCompatActivity() {
    private lateinit var binding : ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.button.setOnClickListener {
            binding.fragmentContainerView.visibility = View.VISIBLE
            supportFragmentManager.commit {
                setReorderingAllowed(true)
                addToBackStack(FragmentA.Companion::class.java.name)
                add(R.id.fragment_container_view, FragmentA.newInstance())
            }
        }
    }

}

Here is the relevant fragment A code :

class FragmentA : Fragment() {

    private val viewModel: SharedViewModel by activityViewModels()
    
    .....
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        fragmentABinding.button.setOnClickListener {
            parentFragmentManager.commit {
                setReorderingAllowed(true)
                addToBackStack(FragmentB.Companion::class.java.name)
                add(R.id.fragment_container_view, FragmentB.newInstance())
            }
        }

        viewLifecycleOwner.lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
                viewModel.sharedFlow.collect { collectedString ->
                    Log.i("FragmentA", collectedString)
                }
            }
        }
    }
}

Here is the relevant fragment B code :

class FragmentB : Fragment() {

    private val viewModel: SharedViewModel by activityViewModels()

    ....
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        viewLifecycleOwner.lifecycleScope.launch {
            repeatOnLifecycle(Lifecycle.State.STARTED) {
                viewModel.sharedFlow.collect { collectedString ->
                    Log.i("FragmentB", collectedString)
                }
            }
        }

        fragmentBBinding.button.setOnClickListener {
            viewModel.setSharedFlow("Hello")
        }
    }

}

Here is my activity scope viewmodel :

class SharedViewModel : ViewModel() {

    private var _sharedFlow = MutableSharedFlow<String>()
    val sharedFlow = _sharedFlow.asSharedFlow()
    
    fun setSharedFlow(string: String) {
        viewModelScope.launch {
            _sharedFlow.emit(string)
        }
    }
}

I have my mainactivity, on the click of a button I add my fragmentA, then on click of another button in fragmentA, I add my fragmentB on top of fragmentA, on the click of a button in fragmentB, I am setting a shared flow in my sharedviewmodel and collecting that sharedflow in both fragments (flow should be collected in fragmentA even if it's in the background), but the collection in fragmentA is not happening, I have tried removing the repeatOnLifecycle(Lifecycle.State.STARTED) block and directly starting collecting in fragmentA like this :

viewLifecycleOwner.lifecycleScope.launch {
            viewModel.sharedFlow.collect { collectedString ->
                Log.i("FragmentA", collectedString)
            }
        }

This seems to be working but I want to achieve this in a lifecycle-aware way recommended by Google, and since the lifecycle of fragmentA doesn't fall below the Destroy state

repeatOnLifecycle(Lifecycle.State.CREATED)

should achieve this. I want to get others' feedback on why the flow in fragment A is not getting collected and how to do it in a lifecycle-aware manner as provided by the repeatOnLifecycle method.

0

There are 0 best solutions below