Is it ok to use sharedPrefrence with Coroutine kotlin

拟墨画扇 提交于 2019-12-10 23:09:25

问题


I have injected sharedPreference in ViewModel.

Can I use android specific resource's while embedding Coroutine scope which automatically suspended when ViewModel loses scope.

I mean is it ok to use preferende in ViewModel if we add a viewModel launch scope

A CoroutineScope keeps track of all coroutines it creates. Therefore, if you cancel a scope, you cancel all coroutines it created

@ContributesViewModel
class SplashViewModel @Inject constructor(private val prefs: PrefStore) : BaseViewModel() {

    val onMoveToNext = ClassLiveData()

    init {
        scope.launch {
            val activity = if(prefs.isLoggedIn()) HomeActivity::class
            else OnBoardingActivity::class
            onMoveToNext.postValue(activity)
        }
    }

    ///fun saveDeviceID(id:String) = prefs.setDeviceID(id)
    //fun createErrorCodeHash() ={}

    fun getIsLoggedIn():Boolean = prefs.isLoggedIn()

    fun setSecondTimeLogin(boolean: Boolean) = prefs.setIsSecondTimeLogin(boolean)
}

Where

abstract class BaseViewModel: ViewModel() {

    private val job = Job()
    val scope = CoroutineScope(Dispatchers.IO + job)

    override fun onCleared() {
        super.onCleared()
        job.cancel()
    }

}

where ClassLiveData

typealias ClassLiveData = MutableLiveData<KClass<*>>

And called it in SplashActivity

viewModel.onMoveToNext.listen(this) {
    Handler().postDelayed({
         val intent = Intent(this, it.java)
        intent.putExtra("Role", "LOGIN")
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
        startActivity(intent)
    }, 2000)

回答1:


As a general rule of thumb, when it comes to keeping a reference to context or other objects that have hard references on context (e.g. ContextWrapper, which is where SharedPrefferences are coming from), one should treat coroutines the same as classic threads.

For example, a live coroutine with Dispathers.IO potentially can leak the context in the same way as a classic thread, AsyncTasks, etc. Therefore, managing these references and cleaning them up is the developers' responsibility.

Looking back at your code, your base ViewModel is working on IO scope, which means any empty-constructor luanches, create a child scope on the same Dispatcher, i.e IO. However because of your ViewModel.onCleared():

override fun onCleared() {
        super.onCleared()
        job.cancel()
    }

you are pretty much safe.

Why am I saying "pretty much"?

Because it depends on how you implement your launches. Remember that only canceling a job doesn't necessarily mean that the corresponding coroutine is close and every reference is removed. Certain implementations need you directly check the state of your job inside the scope and do manual cleanups:

For instance, if you create a while loop inside a coroutine, job.cancel() does not break it, you need to break it manually.

Looking back one last time at your code, you are not doing anything inside your launch that requires manual cleanups. Then, we can say your current code certainly won't leak the context.



来源:https://stackoverflow.com/questions/58536773/is-it-ok-to-use-sharedprefrence-with-coroutine-kotlin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!