【44】kotlin 协程 异步下载图片4 解决线程安全问题

半城伤御伤魂 提交于 2020-07-26 16:02:47

我们的图片地址 是写死的。。但是为了防止出现线程安全问题

我们在async新建

ContextContinuation.kt

package com.yzdzy.kotlin.chapter7.async

import kotlin.coroutines.Continuation
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext

/**
 * Created by benny on 5/29/17.
 */
class ContextContinuation(override val context: CoroutineContext = EmptyCoroutineContext): Continuation<Unit> {


    override fun resumeWith(result: Result<Unit>) {

    }

}

里面不做操作

修改

BaseCoroutines.kt
package com.yzdzy.kotlin.chapter7.basic

import cn.kotliner.coroutine.common.HttpError
import cn.kotliner.coroutine.common.HttpException
import cn.kotliner.coroutine.common.HttpService
import cn.kotliner.coroutine.common.log
import cn.kotliner.coroutine.ui.LOGO_URL
import com.yzdzy.kotlin.chapter7.async.*
import java.lang.Exception
import javax.swing.SwingUtilities
import kotlin.coroutines.*

fun 我要开始协程了(context: CoroutineContext=EmptyCoroutineContext,block: suspend () -> Unit) {
    block.startCoroutine(ContextContinuation(context + AsyncContext()))
}

suspend fun <T> 我要开始耗时操作了(block: CoroutineContext.() -> T) = suspendCoroutine<T> {  continuation ->
    AsyncTask {
        log("异步操作开始前")
//        try {
            val myContnet=continuation.context
            val myBlock=block(myContnet)
            continuation.resume(myBlock)
//        } catch (e: Exception) {
//            log("异步操作开始前e")
//            continuation.resumeWith(Result.failure(e))
//        }
    }.execute()
}


fun 我要开始加载图片了(url: String): ByteArray {
    log("下载图片开始")
    val reponseBody = HttpService.service.getLogo(url).execute()
    if (reponseBody.isSuccessful) {
        reponseBody.body()?.byteStream()?.readBytes()?.let {
            return it
        }
        throw HttpException(HttpError.HTTP_ERROR_NO_DATA)
    } else {
        //切换ui线程
        throw HttpException(reponseBody.code())
    }

}

新建

DownloadContext.kt

package com.yzdzy.kotlin.chapter7.async

import kotlin.coroutines.AbstractCoroutineContextElement
import kotlin.coroutines.CoroutineContext

class DownloadContext (val url:String):AbstractCoroutineContextElement(Key){
    companion object Key:CoroutineContext.Key<DownloadContext>

}

修改 MainKt.kt

package cn.kotliner.coroutine.ui


import cn.kotliner.coroutine.common.HttpError
import cn.kotliner.coroutine.common.HttpService
import cn.kotliner.coroutine.common.log
import com.yzdzy.kotlin.chapter7.async.AsyncTask
import com.yzdzy.kotlin.chapter7.async.DownloadContext
import com.yzdzy.kotlin.chapter7.basic.我要开始加载图片了
import com.yzdzy.kotlin.chapter7.basic.我要开始协程了
import com.yzdzy.kotlin.chapter7.basic.我要开始耗时操作了
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.Callback
import retrofit2.HttpException
import retrofit2.Response
import java.lang.Exception
import javax.swing.JFrame.EXIT_ON_CLOSE
import javax.swing.SwingUtilities

/**
 * Created by benny on 5/20/17.
 */
const val LOGO_URL = "http://www.imooc.com/static/img/index/logo.png?t=1.1"

fun main(args: Array<String>) {
    val frame = MainWindow()
    frame.title = "Coroutine@Bennyhuo"
    frame.setSize(200, 150)
    frame.isResizable = true
    frame.defaultCloseOperation = EXIT_ON_CLOSE
    frame.init()
    frame.isVisible = true

    frame.onButtonClick {

        log("协程之前")
        我要开始协程了(DownloadContext(LOGO_URL)) {
            //为了防止出错。我们一般要做一次异常捕获。这也是协程的好处 只用一次try就好了
            try {
                log("协程开始")
                val imageDate = 我要开始耗时操作了{
                    log(this[DownloadContext]!!.url)
                    我要开始加载图片了(this[DownloadContext]!!.url)
                }
                log("拿到图片")
                frame.setLogo(imageDate)
            }catch (e:Exception){
                e.printStackTrace()
            }

        }
        log("协程之后")
    }


}


 

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