问题描述
我在ViewModel
中注入了sharedPreference
.
我的意思是,如果我们添加一个viewModel启动范围,可以在ViewModel中使用Preferredende
I mean is it ok to use preferende in ViewModel if we add a viewModel launch scope
CoroutineScope跟踪其创建的所有协程.因此,如果您取消范围,则将取消它创建的所有协程
@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)
}
哪里
abstract class BaseViewModel: ViewModel() {
private val job = Job()
val scope = CoroutineScope(Dispatchers.IO + job)
override fun onCleared() {
super.onCleared()
job.cancel()
}
}
其中ClassLiveData
where ClassLiveData
typealias ClassLiveData = MutableLiveData<KClass<*>>
并在SplashActivity中调用它
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)
推荐答案
作为一般经验法则,要保留对context
或在context
上具有硬引用的其他对象的引用(例如,,这是SharedPrefferences
的来源),应将协程与经典线程一样对待.
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.
例如,带有Dispathers.IO
潜在的实时协程可能以与经典thread
,AsyncTasks
等相同的方式泄漏context
.因此,请管理这些引用和清理它们是开发人员的责任.
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.
回头看一下代码,您的基础ViewModel
在IO
范围内工作,这意味着任何空构造器luanch
es都在同一Dispatcher
上创建子范围,即IO
.但是由于您的ViewModel.onCleared()
:
Looking back at your code, your base ViewModel
is working on IO
scope, which means any empty-constructor luanch
es, create a child scope on the same Dispatcher
, i.e IO
. However because of your ViewModel.onCleared()
:
override fun onCleared() {
super.onCleared()
job.cancel()
}
您相当是安全的.
我为什么要说差不多"?
Why am I saying "pretty much"?
因为这取决于您实现launch
es的方式.请记住,仅取消job
并不一定意味着相应的协程已关闭并且所有引用都已删除.某些实现需要您直接在范围内检查作业状态并进行手动清理:
Because it depends on how you implement your launch
es. 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:
例如,如果在协程内部创建一个while循环,job.cancel()
不会破坏,则需要手动break
.
For instance, if you create a while loop inside a coroutine, job.cancel()
does not break it, you need to break
it manually.
最后一次回顾您的代码,您没有在launch
内部执行任何需要手动清理的操作.然后,可以说您当前的代码肯定不会泄漏context
.
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
.
这篇关于可以与Coroutine Kotlin一起使用sharedPrefrence吗的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!