Home > Mobile >  IllegalStateException after using lifeCycleScope
IllegalStateException after using lifeCycleScope

Time:01-12

I have used viewLifecycleOwner.lifecycleScope and also tried converted uploadPhoto StateFlow to LiveData but still my App crashes at dismiss loadingDialogFragment

LoadingDialogFragment.kt

class LoadingDialogFragment : DialogFragment() {

    private lateinit var mBinding: DialogLoaderBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setStyle(STYLE_NO_TITLE, R.style.FullScreenDialogStyle)
        isCancelable = false
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        mBinding = DialogLoaderBinding.inflate(inflater, container, false)
        return mBinding.root
    }

    override fun show(manager: FragmentManager, tag: String?) {
        ///super.show(manager, tag)
        try {
            val ft: FragmentTransaction = manager.beginTransaction()
            ft.add(this, tag).addToBackStack(null)
            ft.commitAllowingStateLoss()
        } catch (e: IllegalStateException) {
            Log.e("IllegalStateException", "Exception", e)
        }
    }
}

ProfileFragment -> onViewCreated

viewLifecycleOwner.lifecycleScope.launchWhenCreated {
                mViewModel.uploadPhoto.collectLatest {
                    if (it.isLoading) {
                        loadingDialogFragment = LoadingDialogFragment()
                        loadingDialogFragment?.show(childFragmentManager, "loadingDialogFragment")
                    }
                    it.error?.let {
                        loadingDialogFragment?.dismiss() //crashed at here 
                        Toast.makeText(requireContext(), "No ", Toast.LENGTH_SHORT)
                            .show()

                    }

                    it.data?.let {
                        loadingDialogFragment?.dismiss() //crashed at here 
                    }
            }
        }

As far as my understanding is concern collectLatest code should not work when app activity or fragment is in onPause|onStop or onDestroy state.

CodePudding user response:

I have faced this similar issue as well

  • I have solved this issue by using

    viewLifecycleOwner.lifecycleScope.launch {
    viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
     // {code to collect from viewModel}
     }
    }
    

So , your code would be look like

viewLifecycleOwner.lifecycleScope.launch {
            viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED){
                mViewModel.uploadPhoto.collectLatest {
                    if (it.isLoading) {
                        loadingDialogFragment = LoadingDialogFragment()
                        loadingDialogFragment?.show(childFragmentManager, "loadingDialogFragment")
                    }
                    it.error?.let {
                        loadingDialogFragment?.dismiss()
                        Toast.makeText(requireContext(), "No ", Toast.LENGTH_SHORT)
                            .show()
                    }
                    it.data?.let {
                        loadingDialogFragment?.dismiss()
                    }
                }
            }
        }
  • How it works

repeatOnLifecycle is a suspend function. As such, it needs to be executed within a coroutine. repeatOnLifecycle suspends the calling coroutine, and then runs a given suspend block that you pass as a parameter in a new coroutine each time the given lifecycle reaches a target state or higher. If the lifecycle state falls below the target, the coroutine launched for the block is cancelled. Lastly, the repeatOnLifecycle function itself won’t resume the calling coroutine until the lifecycle is DESTROYED.

  • Related