美文网首页
kotlin 协程一

kotlin 协程一

作者: crossroads | 来源:发表于2020-12-30 21:17 被阅读0次

    前言

    趁机学一下kotlin协程,笔记来自安卓官网。关于协程的一些理解,大家可以看 抛物线的视频,B站就有,讲的很透彻。这个主要对于官网学习网站的翻译,学习网站见后记。官网的是中文,就不写在这里了。写的有点乱,主要用于回顾。

    理解

    1. 协程都要运行在CoroutineScope中,一个scope通过其工作控制协程的生命,当取消scope,就会取消在这个scope里的所有协程。
    2. 因为协程可以很容易的在任何时间切换线程,并且返回结果给源线程,所以在主线程开始一个UI关联的协程是个好方式。例如ROOM、retrofit这些库在使用协程时是主线程安全的,所以不需要使用者在网络或者数据库调用时去管理线程。
    3. viewmodelScope 是viewmodel的扩展,这个scope被绑定在Dispatchers.Main上,当viewmodel被清除时会自动cancel。

    代码示例

    1. viewModelScope的调度器是Dispatchers.Main,这里运行在主线程



      最左边的箭头+波浪线的符号应该是用了协程的标志
      2.使用协程
      首先,使用suspend操作符告诉kotlin,这个方法和协程一起工作

    suspend fun refreshTitle() {
        delay(500)
    }
    
       viewModelScope.launch {
                try {
                    _spinner.value = true
                    repository.refreshTitle()
                } catch (error: TitleRefreshError) {
                    _snackBar.value = error.message
                } finally {
                    _spinner.value = false
                }
            }
    
    1. 切换线程
      1》之前主线程安全的方法,类似这样:
        fun refreshTitleWithCallbacks(titleRefreshCallback: TitleRefreshCallback) {
            Executors.newFixedThreadPool(2).submit {
                try {
                    val result = network.fetchNextTitle().execute()
                    if (result.isSuccessful) {
                        titleDao.insertTitle(Title(result.body()!!))
                        titleRefreshCallback.onCompleted()
                    } else {
                        titleRefreshCallback.onError(
                                TitleRefreshError("Unable to refresh title", null))
                    }
                } catch (cause: Throwable) {
                    titleRefreshCallback.onError(
                            TitleRefreshError("Unable to refresh title", cause))
                }
            }
        }
    

    那么协程中会如何做呢?

      suspend fun refreshTitleWithCallbacks() {
            withContext(Dispatchers.IO) {
                val result = try {
                    network.fetchNextTitle().execute()
                } catch (cause: Throwable) {
                    throw  TitleRefreshError("Unable to refresh title", null)
                }
                if (result.isSuccessful) {
                    titleDao.insertTitle(Title(result.body()!!))
                } else {
                    throw  TitleRefreshError("Unable to refresh title", null)
                }
            }
        }
    

    注意:这里暂没有去做cancel操作,一般来说是需要在必要的时候明确cancel的。

    1. diapatcher 调度器介绍
      Main:主线程 ;IO: 从网络或者数据库读取数据;Default:CPU密集型工作
    2. 在room和retrofit中
      1>retrofit
    interface MainNetwork {
     @GET("next_title.json")
    //改变前   fun fetchNextTitle(): Call<String>
    suspend fun fetchNextTitle(): String
    }
    

    2>room

      @Insert(onConflict = OnConflictStrategy.REPLACE)
        //改变前   fun insertTitle(title: Title)
    suspend fun insertTitle(title: Title)
    

    3>方法

        suspend fun refreshTitleWithCallbacks() {
            try {
                val result = network.fetchNextTitle()
                titleDao.insertTitle(Title(result))
            } catch (cause: Throwable) {
                throw  TitleRefreshError("Unable to refresh title", null)
            }
        }
    

    如果设置5s请求超时

       suspend fun refreshTitleWithCallbacks() {
            try {
                val result = withTimeout(5000){
                    network.fetchNextTitle()
                }
                titleDao.insertTitle(Title(result))
            } catch (cause: Throwable) {
                throw  TitleRefreshError("Unable to refresh title", null)
            }
        }
    
    1. 抽suspend方法当参数进行封装
      咱们使用2使用协程的代码来进行封装抽取
       fun launchDataLoad(block: suspend () -> Unit): Job {
            return viewModelScope.launch {
                try {
                    _spinner.value = true
                    block()
                } catch (error: TitleRefreshError) {
                    _snackBar.value = error.message
                } finally {
                    _spinner.value = false
                }
            }
        }
        fun refreshTitle() {
            launchDataLoad {
                repository.refreshTitle()
            }
        }
    

    学习网站

    官网
    官网学习网站

    后记

    携程取消方式
    进阶 Part 1: Coroutines, Part 2: Cancellation in coroutines, and Part 3: Exceptions in coroutines
    在livedata中使用 及其他进阶后续再写。

    相关文章

      网友评论

          本文标题:kotlin 协程一

          本文链接:https://www.haomeiwen.com/subject/jsolbktx.html