android - 使用改造和 kotlin channel 实现长轮询

标签 android kotlin android-lifecycle polling long-polling

我正在尝试实现生命周期感知的长轮询(在 Activity/fragment 中)。轮询的范围将限于每隔固定时间间隔向服务器发送 API 请求的 fragment 。但是,我无法实现它。

这就是我希望实现的样子

  • Have a hard timeout on client-side without considering any extra delay incurred in receiving the response.
  • Wait for the response of previous API call before sending the next request. i.e., the request in polling queue should wait for response irrespective of its priority due to polling interval


考虑:

HARD_TIMEOUT = 10 秒

POLLING_INTERVAL = 2s
enter image description here
 Request 1: Started at: 0sec      Response delay:1.2sec   Duration left: 0.8sec
 Request 2: Started at: 2sec      Response delay:0.4sec   Duration left: 1.6sec
 Request 3: Started at: 4sec      Response delay:2.5sec   Duration left: 0sec
 Request 4: Started at: 6.5sec    Response delay:0.5sec   Duration left: 1.0sec
 Request 5: Started at: 8sec      Response delay:0.8sec   Duration left: 1.2sec

对于这个用例,我想使用轮询而不是套接字。任何想法/解决方案将不胜感激。谢谢你。

最佳答案

好的,想出了一个使用 channel 进行轮询的解决方案。这应该可以帮助某人搜索示例。

    private val pollingChannel = Channel<Deferred<Result<OrderStatus>>>()
    val POLLING_TIMEOUT_DURATION = 10000L
    val POLLING_FREQUENCY = 2000L

A channel is required to hold your asynchronous request just in case more request comes in while your async task is being executed.


    val pollingChannel = Channel<Deferred<Pair<Int,Int>>>()

QUEUE EXECUTOR: It will pick an async task and start executing them in FIFO order.


    CoroutineScope(Dispatchers.IO).launch {
        for (i in pollingChannel) {
            val x = i.await()
            println("${SimpleDateFormat("mm:ss.SSS").format(Calendar.getInstance().time)} Request ${x.first}: value ${x.second}")
        }
    }

POLLING FUNCTION: Adds your async task to the polling channel every fixed interval of time until timeout.


    CoroutineScope(Dispatchers.IO).launch {
        var reqIndex = 1
        val timedOut = withTimeoutOrNull(POLLING_TIMEOUT_DURATION) {
            while (receiverJob.isActive) {
                pollingChannel.send(async {
                    getRandomNumber(reqIndex++)
                })
                delay(POLLING_FREQUENCY)
            }
        }
    }

ASYNCHRONOUS OPERATION



为避免回答冗长,我创建了一个随机延迟的函数,请替换为所需的 API 调用
   private suspend fun getRandomNumber(index: Int): Pair<Int,Int> {
    val randomDuration = (1..6L).random() * 500
    delay(randomDuration)
    return Pair(index,(0..100).random())
}

样本输出

enter image description here

关于android - 使用改造和 kotlin channel 实现长轮询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61056548/

相关文章:

android - Android应用程序启动时如何启动Service?

android-lifecycle - RoboSpice shouldStop() 真的需要吗?

Android 数据在 startActivity() 回调后 onCreate() 丢失

android - kotlin 中的 MPAndroid 饼图

android - viewBinding为什么让XML根全屏

android - 删除 fragment 后内存未释放

java - 如何在android中创建我自己的com.google.android.gms.tasks.Task?

arrays - 如何从Kotlin中的ArrayList中删除项目

android - 全屏 Intent 不启动 Activity,但在 Android 10 上显示通知

android - 如何以编程方式强制停止应用程序-Android