Kotlin coroutines, continues updates

柔情痞子 提交于 2019-12-11 15:26:49

问题


New to kotlin, i tried many examples and tutorials to no avail, My requirement is:

  • Ui creates a coroutine that initiates a network connection

  • on press of a button, that coroutine sends a msg like "i need info about foo" (taken from a edittext?) to the connected server.

  • coroutine should also be listening for incoming messages and pass those messages to ui (or update ui directly)

  • coroutine should keep connected to the server unless it is told to close the connection.

I feel that i need global scope, dispatcher.io.

All the examples i found do nothing more than printing values and terminating coroutines and doesn't mention how to implement a long running coroutine which can act as a continues background socket connection.

I do understand that listening from a socket in loop can achieve that but what kind of coroutine do i need here and how do i send messages to and from ui?

Update:Code

// 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()
        }
    }
}

}

New Question: How do i handle configuration changes :(

Answer: I used Fragments with ViewModels and coroutine launched via viewmodelScope, working flawlessly so far.


回答1:


From what I understand you want to create a coroutine that listens for responses over a connection. In that case the only thing that you need make sure is that the coroutine should be cancellable, once activity is closed.

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 is an extension property available inside the coroutine via the CoroutineScope object.

When the screen is rotated, the connection is closed and a new one is being opened once the coroutine is called again in onCreate.



来源:https://stackoverflow.com/questions/57717328/kotlin-coroutines-continues-updates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!