阅读 632

Kotlin(十)Kotlin协程应用

  • 需求分析
  • 效果展示
  • Coding

需求分析

如何让普通函数适配协程,成为“真正的挂起函数”。即让调用方以同步的方式拿到异步任务返回结果

//场景描述
fun getConfigContent(){
  parseAssetsFile("config.json"){fileContent->
    println(fileContent)
  }
}

//CoroutineScene4.kt
fun parseAssetsFile(fileName:String,callback(String)->Unit){
  Thread(Runnable {
       //readfile(filename)  
        Thread.sleep(2000)
        callback("assets file content") 
       }).start()
    }
}
复制代码

方案一

lifecycleScope.launch{
  val fileContent =   lifecycleScope.async{parseAssetsFile()}.await()
  //delay()
  println(fileContent)
}

suspend parseAssetsFile(fileName:String):String{
  return "assets file content"
}
复制代码

方案二

lifecycleScope.launch{
  val fileContent = parseAssetsFile()
  println(fileContent)
}

suspend parseAssetsFile(fileName:String):String{
  //suspendCoroutine
  return suspendCancellableCoroutine { continuation ->
        Thread{
          //io ....
        continuation.resumeWith(Result.success("assets file content")) 
        }.start()                               
  }
}
复制代码
public suspend fun delay(timeMillis: Long) {
    return suspendCancellableCoroutine sc@ { cont: CancellableContinuation<Unit> ->
        cont.context.delay.scheduleResumeAfterDelay(timeMillis, cont)
    }
}
复制代码

一个例子

/**
 *
 * @Author:      jarrysong
 * @CreateDate:  2021/4/8 0:24
 * @Description: 演示以异步的方式,读取assets目录下的文件,并且适配协程的写法,让他真正的挂起函数
 * 
 * 方便调用,直接以同步的形式拿到返回值
 * @Version:
 */
object CoroutineScene3 {

    private const val TAG = "CoroutineScene3"


    suspend fun parseAssetFile(assManager:AssetManager,fileName:String):String{
        return suspendCancellableCoroutine { continuation ->
            Thread(Runnable{
                val inputStream = assManager.open(fileName)
                val br = BufferedReader(InputStreamReader(inputStream))
                var line:String?
                var stringBuilder = StringBuffer()
                do{
                    line = br.readLine();
                    if(line != null) stringBuilder.append(line) else break
                }while (true)
                inputStream.close()
                br.close()
                Thread.sleep(2000)
                Log.i(TAG,"parseassetsfile completed")
                continuation.resumeWith(Result.success(stringBuilder.toString()))
            }).start()
        }
    }
}
复制代码

调用

 lifecycleScope.launch {
           val content = CoroutineScene3.parseAssetFile(assets ,"file.json")
            Log.i(TAG,content)
        }
Log.i(TAG,"start")
复制代码

注意:

在Activity中建议用lifecycleScope.launch来启动协程,会随着Activity的生命周期自动销毁协程。

如果用GlobalScope.launch来启动,生命周期是Application,会导致内存泄漏。

image-20201217081923402

Retrofit如何适配协程

参考:github.com/square/retr…

image-20201217082246780

文章分类
Android
文章标签