withContext(Dispatchers.IO) 与 viewModelScope.launch(Dispatchers.IO) 的区别

文章目录

    CoroutineScope withContext lifecycleScope viewModelScope 该如何选择

    CoroutineScope, withContext, lifecycleScope, 和 viewModelScope 是 Android 中用于协程管理的不同组件和类。这些组件和类可以帮助您在 Android 应用程序中正确地使用协程。

    • CoroutineScope:是一个顶层接口,用于管理协程以及它们运行的线程。您可以使用GlobalScope创建全局作用域,但通常建议为每个组件或任务创建自己的范围,以便在需要终止时可以更好地控制它们。
    • withContext:是一个Suspend函数,可用于在协程中切换上下文(线程)。它允许您在不阻塞UI线程的情况下执行长时间运行的代码,并将结果返回到主线程。
    • lifecycleScope:是Android Jetpack组件中的一部分,它提供了一个协程范围,该范围受到与组件生命周期相关的限制。例如,当Activity或Fragment被销毁时,此作用域也会自动清除。
    • viewModelScope:是Jetpack库中的ViewModel组件的一部分,适用于在ViewModel中启动协程。与lifecycleScope不同,此范围将保留ViewModel的生命周期,并在ViewModel被清除时取消其所有协程。

    选择何种范围取决于您的需求。例如:

    • 如果您只是想在后台线程上执行一些长时间运行的代码,而无需与任何特定的生命周期相关,请使用CoroutineScope
    • 如果您需要在协程中切换上下文以避免阻塞UI线程,请使用withContext或其他CoroutineScope。
    • 如果您正在使用Android Jetpack库中的组件(如Activity或Fragment),并且要确保在组件被销毁时取消所有协程,请使用lifecycleScope
    • 如果您正在使用ViewModel,并且要确保在ViewModel被清除时取消其所有协程,请使用viewModelScope

    viewModelScope 的作用

    viewModelScope.launch(Dispatchers.IO) {
        // do something
    }
    
    • viewModelScope 是一个内置的 CoroutineScope,包含在 ViewModel KTX 扩展中
    • Dispatchers.IO 是为了注明当前 coroutine 需要运行在一个用来执行 I/O 操作的线程中

    当用户从一个界面退出,其对应的 ViewModel 会被销毁,相应的此 ViewModel 的 viewModelScope 会被自动取消 (cancelled),所有运行在 viewModelScope 中的 coroutine 也会被取消。

    所以,没人会用 CoroutineScope.launch,原因就是当 UI 界面退出,但是 coroutine 运行时间过长,这个 coroutine 将得不到清理。

    withContext(Dispatchers.IO) 与 viewModelScope.launch(Dispatchers.IO) 的区别

    首先 withContext 也是一个 suspend function,所以 withContext 必须在 suspend 函数,或者 coroutine 中被调用。

    • viewModelScope.launch(Dispatchers.IO),即 launch 的 coroutine 运行之后,不再返回数据
    • withContext(Dispatchers.IO) 会将 coroutine 的返回值,作为当前函数的返回

    例如:

    suspend fun updatePage() {                      
        val result = getDataFromServer("www.sunzhongwei.com")  
        show(result)                               
    }
    
    suspend fun getDataFromServer(url: String) =                 
        withContext(Dispatchers.IO) {              
            // 执行网络请求          
        }                                          
    

    viewModelScope 需要在 ViewModel 中使用

    参考

    https://medium.com/androiddevelopers/easy-coroutines-in-android-viewmodelscope-25bffb605471

    参考

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式