5
votes

I am using AutoClearedValue class from this link and when view is destroyed, backing field becomes null and that is good but i have a thread(actually a kotlin coroutine) that after it is done, it accesses the value(which uses autoCleared) but if before it's Job is done i navigate to another fragment(view of this fragment is destroyed), then it tries to access the value, but since it is null i get an exception and therefore a crash. what can i do about this?

also for which variables this autoCleared needs to be used? i use it for viewBinding and recyclerview adapters.

1
Can't you put null check before access ?Android Killer
nullable field is in autoClearedValue, so i do not have access to it. i can put everything in try/catch but that is something that can be forgot and cause problemsmohsen sameti
@mohsensameti you should call coroutine in lifecycle aware fashion. So the update only happens when the view is at least started. for eg., if you're calling a web service then you should overserve the response and when the response comes live data won't notify your fragment because it is destroyed.Somesh Kumar

1 Answers

0
votes

You have 2 option:

1- Cancelling all the running job(s) that may access to view after its destruction. override onDestroyView() to do it.

Also, you can launch the coroutines viewLifecycleOwner.lifecycleScope to canceling it self when view destroy.

viewLifecycleOwner.lifecycleScope.launch {
    // do sth with view    
}

2- (Preferred solution) Use Lifecycle aware components (e.g LiveData) between coroutines and view:

coroutines push the state or data in the live-data and you must observe it with viewLifeCycleOwner scope to update the view.

private val stateLiveData = MutableLiveData<String>()

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

    stateLiveData.observe(viewLifecycleOwner) { value ->
        binding.textView.text = value
    }
}

private fun fetchSomething() {
    lifecycleScope.launch {
        delay(10_000)
        stateLiveData.value = "Hello"
    }
}