使用Coroutine进行连续数据轮询并将其倾倒到UI

发布于 2025-01-22 21:47:42 字数 774 浏览 0 评论 0原文

我现有的Android代码使用asynctask虚拟com 端口连续进行轮询数据,并通过覆盖onprogressupdate()函数来将数据转移到UI线程中。如下:

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 
  }  
}

上面的代码正常工作(除了在此处和那里进行一些内存泄漏警告外)。

时不时地,我看到coroutine被促进以执行并发和异步操作,并且发现被迫尝试用coroutine替换asynctask。 OTOH,我没有完全掌握coroutines的工作,以替代asynctask。因此,我的问题是coroutine是否是可行的更换我的用例(连续数据轮询和在UI上倾倒)。任何优秀的高级(或伪)例子 欢迎在那里证明这种用例。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

冷月断魂刀 2025-01-29 21:47:44

很难假设您在asynctask的串行端口上的收听方式,无论您是使用某种侦听器还是无限循环,但是我想使用 flow mvvm方法。它的外观如下:

在存储库类中:

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
}

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(activityfragment):

vm.state
        .flowWithLifecycle(lifecycle)
        .onEach { state ->
            // handle all states
            if (state is Dump) {
                val data = state.data
                // use data
            }
    }.launchIn(lifecycleScope)

如果您不是是使用mvvm体系结构的方法的粉丝,您可以在UI类中完成所有操作(活动fragment),我我不喜欢t建议:

listenPort().flowWithLifecycle(lifecycle)
        .onEach { data ->
            // use data
        }.launchIn(lifecycleScope)

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文