首页 > 解决方案 > Kotlin 协程,持续更新

问题描述

kotlin 新手,我尝试了很多示例和教程都无济于事,我的要求是:

我觉得我需要全局范围,dispatcher.io。

我发现的所有示例都只是打印值和终止协程,并没有提到如何实现一个可以充当持续后台套接字连接的长时间运行的协程。

我确实知道从循环中的套接字监听可以实现这一点,但是我在这里需要什么样的协程以及如何向 ui 发送消息和从 ui 发送消息?

更新:代码

// Added comments for new devs who love copy-pasting as it is a nice little startup code
// you can add android:screenOrientation="portrait" in manifest if you want to use this code
class MainActivity2 : AppCompatActivity(), CoroutineScope {
override val coroutineContext: CoroutineContext
    get() = Dispatchers.Main + job

private lateinit var job: Job // lateinit = will be initialized later 

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main2)
    job = Job() // initialized 
    launch(Dispatchers.IO) { //dispatcher defined, otherwise launch{
        // activity also extends coroutine scope so it will be launched in that scope
        connector()
    }
}

override fun onDestroy() {
    // to avoid launching multiple coroutines
    // on configuration changes and cancelling it on exit
    job.cancel() 
    super.onDestroy()
}

suspend fun connector() = withContext(Dispatchers.IO){ //defined dispatcher twice here
// useless, once is enough, either here or on launch
//if you defined dispatcher on launch, fun should look like
// suspend fun connector(){
    while(true){
        // talk to a server
        // need to update ui? 
        withContext(Dispatchers.Main){ // back to UI
            // you can update/modify ui here
            Toast.makeText(this@MainActivity2, "hi there", Toast.LENGTH_LONG).show()
        }
    }
}

}

新问题:我如何处理配置更改 :(

答:我使用 Fragments 与 ViewModels 和通过 viewmodelScope 启动的协程,到目前为止工作完美。

标签: androidkotlinkotlin-coroutines

解决方案


据我了解,您希望创建一个通过连接侦听响应的协程。在这种情况下,您唯一需要确保的是,一旦活动关闭,协程应该是可取消的。

suspend fun connector() = withContext(Dispatchers.IO){
    try {
        // open the connection here
        while(isActive) {
        var doing  : String = "nothing" // fetched from a network call
              withContext(Dispatchers.Main){
                Toast.makeText(this@MainActivity2, doing, Toast.LENGTH_LONG).show()
            }
        }
    } finally {
        withContext(NonCancellable) {
            //close the connection here     
        }   
    }

isActive是通过CoroutineScope对象在协程内部可用的扩展属性。

当屏幕旋转时,连接被关闭,一旦协程再次被调用,新的连接就会被打开onCreate


推荐阅读