使用改造和 kotlin 通道实现长轮询

sud*_*esh 6 android polling long-polling android-lifecycle kotlin

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

这就是我希望实现的样子

  • 在客户端有一个硬超时,而不考虑在接收响应时产生的任何额外延迟。
  • 在发送下一个请求之前等待上一个 API 调用的响应。即,由于轮询间隔,轮询队列中的请求应等待响应,而不管其优先级如何

考虑:

HARD_TIMEOUT = 10 秒

POLLING_INTERVAL = 2 秒 在此处输入图片说明

 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
Run Code Online (Sandbox Code Playgroud)

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

sud*_*esh 4

好的,找到了使用通道进行轮询的解决方案。这应该有助于寻找示例的人。

    private val pollingChannel = Channel<Deferred<Result<OrderStatus>>>()
    val POLLING_TIMEOUT_DURATION = 10000L
    val POLLING_FREQUENCY = 2000L
Run Code Online (Sandbox Code Playgroud)

需要一个通道来保存您的异步请求,以防在执行异步任务时出现更多请求。

    val pollingChannel = Channel<Deferred<Pair<Int,Int>>>()
Run Code Online (Sandbox Code Playgroud)

队列执行器:它将选择一个异步任务并开始按 FIFO 顺序执行它们。

    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}")
        }
    }
Run Code Online (Sandbox Code Playgroud)

轮询功能:每隔固定的时间间隔将异步任务添加到轮询通道,直到超时。

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

异步操作

为了避免答案冗长,我创建了一个具有随机延迟的函数,请替换为所需的 API 调用

   private suspend fun getRandomNumber(index: Int): Pair<Int,Int> {
    val randomDuration = (1..6L).random() * 500
    delay(randomDuration)
    return Pair(index,(0..100).random())
}
Run Code Online (Sandbox Code Playgroud)

样本输出

在此输入图像描述