协程通过将复杂性放入库来简化异步编程。程序的逻辑可以在协程中顺序地表达,而底层库会为我们解决其异步性。该库可以将用户代码的相关部分包装为回调、订阅相关事件、在不同线程(甚至不同机器)上调度执行,而代码则保持如同顺序执行一样简单。
作者:JohnnyShieh
链接:https://www.jianshu.com/p/2659bbe0df16
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
需求:
获取网络上的图片,处理后,显示出来。
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
}