协程通过将复杂性放入库来简化异步编程。程序的逻辑可以在协程中顺序地表达,而底层库会为我们解决其异步性。该库可以将用户代码的相关部分包装为回调、订阅相关事件、在不同线程(甚至不同机器)上调度执行,而代码则保持如同顺序执行一样简单。

作者:JohnnyShieh
链接:https://www.jianshu.com/p/2659bbe0df16
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

需求:

获取网络上的图片,处理后,显示出来。

  1. val imgUrl = "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fa2.att.hudong.com%2F42%2F31%2F01300001320894132989315766618.jpg&refer=http%3A%2F%2Fa2.att.hudong.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1612336812&t=5d19a6ef830311ec610dd50343a1ecb8"

协程

CoroutineScope(Dispatchers.Main).launch {
            var bitmap = getUrlImage(imgUrl)
            bitmap = bitmap.createWaterMark( "Mr.S")
            image.setImageBitmap(bitmap)
        }

从流程上来,并没有暴露出线程切换,只是简单的线性调用,符合我们的思维。

kotlin

        thread {
            getUrlImage2(imgUrl) {
                it.createWaterMark2("Mr.S") {
                    runOnUiThread {
                        image.setImageBitmap(it)
                    }
                }
            }
        }

Rx + kotlin

        Observable.create<Bitmap> {
            it.onNext(getUrlImage3(imgUrl))
        }.map {
            it.createWaterMark3("Mr.S")
        }.subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe {
                    image.setImageBitmap(it)
                }
    }

        Single.fromCallable {
            getUrlImage3(imgUrl)
        }.map {
            it.createWaterMark3("Mr.S")
        }.subscribeOn(Schedulers.newThread())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe { bitmap -> image.setImageBitmap(bitmap) }
    suspend fun getUrlImage(imgageUrl: String) = withContext(Dispatchers.IO) {
        val url = URL(imgageUrl)
        val openConnection = url.openConnection() as HttpURLConnection
        openConnection.requestMethod = "GET"
        openConnection.connect()
        val inputStream = openConnection.inputStream
        BitmapFactory.decodeStream(inputStream)
    }

    suspend fun Bitmap.createWaterMark(mark: String) = withContext(Dispatchers.IO) {
        val w = width
        val h = height
        val bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bmp)
        val paint = Paint()
        paint.color = Color.parseColor("#c5ff0000")
        paint.textSize = 150f
        paint.isAntiAlias = true
        canvas.drawBitmap(this@createWaterMark, 0f, 0f, paint)
        canvas.drawText(mark, 0f, (h / 2).toFloat(), paint)
        bmp
    }


        fun getUrlImage2(imgageUrl: String, cb: (Bitmap) -> Unit) {
        val url = URL(imgageUrl)
        val openConnection = url.openConnection() as HttpURLConnection
        openConnection.requestMethod = "GET"
        openConnection.connect()
        val inputStream = openConnection.inputStream
        val bitmap = BitmapFactory.decodeStream(inputStream)
        cb(bitmap)
    }

    fun Bitmap.createWaterMark2(mark: String, cb: (Bitmap) -> Unit) {
        val w = width
        val h = height
        val bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bmp)
        val paint = Paint()
        paint.color = Color.parseColor("#c5ff0000")
        paint.textSize = 150f
        paint.isAntiAlias = true
        canvas.drawBitmap(this, 0f, 0f, paint)
        canvas.drawText(mark, 0f, (h / 2).toFloat(), paint)
        cb(bmp)
    }

    fun getUrlImage3(imgageUrl: String): Bitmap {
        val url = URL(imgageUrl)
        val openConnection = url.openConnection() as HttpURLConnection
        openConnection.requestMethod = "GET"
        openConnection.connect()
        val inputStream = openConnection.inputStream
        return BitmapFactory.decodeStream(inputStream)
    }

    fun Bitmap.createWaterMark3(mark: String): Bitmap {
        val w = width
        val h = height
        val bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bmp)
        val paint = Paint()
        paint.color = Color.parseColor("#c5ff0000")
        paint.textSize = 150f
        paint.isAntiAlias = true
        canvas.drawBitmap(this, 0f, 0f, paint)
        canvas.drawText(mark, 0f, (h / 2).toFloat(), paint)
        return bmp
    }