Issue
My existing Android code uses AsyncTask
to continuously poll data from a virtual COM port and dumps data to UI thread by overriding the onProgressUpdate()
function. Something like the following:
open class ComActivity(deviceID:Int, listener: OnComRxUpdateUI) : AsyncTask<..., ..., ...>(){
...
override fun doInBackground(...) {
... //keep listening on serial port and transfer byte to buffer when available
}
override fun onProgressUpdate(...){
... //dump to ui
}
}
The above code works fine (except for some memory leak warnings here and there).
Every now and then, I see Coroutine
being promoted for performing concurrent, and asynchronous operations, and I find compelled to try replacing AsyncTask
with Coroutine. OTOH, I do not fully grasp the working of Coroutines
as a substitute for AsyncTask
. So my question is whether Coroutine
is a viable replacement for my use case (continuous data polling and dumping on UI). Any good high-level (or pseudo) example
out there that demonstrate this use case are welcome.
Solution
It is hard to assume how you are listening on a serial port in AsyncTask
, whether you use some kind of listener or an infinite loop, but I guess the same result can be achieved using Flow
and MVVM
approach. It will look something like the following:
In Repository class:
fun listenPort(): Flow<String> = flow {
// keep listening on serial port, use emit() function to emit data
while (true) {
val data = listen()
emit(data)
}
}
suspend fun listen() = withContext(Dispatchers.IO) {
// listening on serial port
}
In ViewModel
:
private val _state = MutableStateFlow<State>(Loading)
val state = _state
init {
repository.listenPort()
.onEach { data ->
_state.value = Dump(data)
}.launchIn(viewModelScope)
}
States:
sealed interface State
object Loading : State
data class Dump(val data: ...) : State
In Ui(Activity
or Fragment
):
vm.state
.flowWithLifecycle(lifecycle)
.onEach { state ->
// handle all states
if (state is Dump) {
val data = state.data
// use data
}
}.launchIn(lifecycleScope)
If you are not a fan of the approach of using MVVM
architecture, you can do all of it in UI class(Activity
or Fragment
), which I don't recommend:
listenPort().flowWithLifecycle(lifecycle)
.onEach { data ->
// use data
}.launchIn(lifecycleScope)
Answered By - Sergio
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.