【问题标题】:Implementing long polling with retrofit and kotlin channels使用改造和 kotlin 通道实现长轮询
【发布时间】:2020-04-06 09:20:43
【问题描述】:

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

这就是我希望实现的样子

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

考虑:

HARD_TIMEOUT = 10 秒

POLLING_INTERVAL = 2s

 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

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

【问题讨论】:

  • 可以使用ticker,例如pl.kotl.in/mP5Rl4k0K
  • @IR42 代码使用 ObsoleteCoroutinesApi 进行注释,无法在生产中使用,重新设计可能会崩溃或使应用程序出现意外行为。

标签: android kotlin android-lifecycle polling long-polling


【解决方案1】:

好的,想出了一个使用频道进行轮询的解决方案。这应该有助于搜索示例的人。

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

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

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

QUEUE EXECUTOR:它将选择一个异步任务并开始以先进先出的顺序执行它们。

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

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

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

异步操作

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

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

样本输出

【讨论】:

    猜你喜欢
    • 2013-02-17
    • 2012-10-06
    • 1970-01-01
    • 2011-09-16
    • 2012-06-02
    • 2014-01-08
    • 2016-03-10
    • 2012-04-01
    • 1970-01-01
    相关资源
    最近更新 更多