android - Kotlin 协程,持续更新
问题描述
kotlin 新手,我尝试了很多示例和教程都无济于事,我的要求是:
ui 创建一个启动网络连接的协程
按下按钮后,该协程会向连接的服务器发送一条消息,例如“我需要有关 foo 的信息”(取自编辑文本?)。
协程还应该监听传入的消息并将这些消息传递给 ui(或直接更新 ui)
协程应该保持与服务器的连接,除非它被告知关闭连接。
我觉得我需要全局范围,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 启动的协程,到目前为止工作完美。
解决方案
据我了解,您希望创建一个通过连接侦听响应的协程。在这种情况下,您唯一需要确保的是,一旦活动关闭,协程应该是可取消的。
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
。
推荐阅读
- c - 创建作为文档父节点的新节点
- css - 在 Microsoft Edge 中,与 dir "rtl" 属性结合使用时,粘性定位不起作用
- c# - 编写一些接受整数的代码,并以螺旋格式打印从 0 到该输入整数的整数
- symfony - Sonata Admin Bundle 列出组的用户
- c# - 如何在运行时读取给定项目中的 MSBuild 属性?
- docker - 如何在 Windows 中找到 Docker 容器可用的地址?
- c# - PDF中的段落阅读
- javascript - 我的工作代码中有错误。它不能正常工作
- mobile - Appium_Error : 返回值无法使用 Xcode 10.0 转换为 WebElement
- javascript - 有没有办法在浏览器窗口之外跟踪鼠标事件?