【问题标题】:Can I tell Retrofit to ignore OkHttp Dispatcher?我可以告诉 Retrofit 忽略 OkHttp Dispatcher 吗?
【发布时间】:2022-08-19 23:44:22
【问题描述】:

我在一个应用程序中遇到了一种情况,同一端点(具有不同参数)同时有很多网络调用。这可能会导致其他呼叫被阻止。

该设置使用 Retrofit + Kotlin 协程。

我能想到的一种解决方案是使用单独的线程池使用不同的 Retrofit+OkHttp 实例运行调用。

但是,我更喜欢通过不同的 kotlin 协程调度程序和使用 limitedParallelism() 来定义限制的单个线程池(和 Retrofit 实例)。

看到这个代码sn-p:

class NetworkApi(
    private val retrofitWebserviceApi: RetrofitWebserviceApi,
    threadPoolExecutor: ThreadPoolExecutor,
    private val dispatcher: CoroutineDispatcher = threadPoolExecutor.asCoroutineDispatcher()
        .limitedParallelism(CoroutineDispatcherConfig.ioDispatcherLimit),
    // A separate IO dispatcher pool so the many calls to getEntries don\'t block other calls
    private val noParallelismDispatcher: CoroutineDispatcher = dispatcher.limitedParallelism(1),
) {
    /**
     * Represents an endpoint, which needs to be called with a lot of different 
     * parameters at the same time (about 1000 times).
     * It\'s important these calls don\'t block the whole thread pool.
     */
    suspend fun getEntries(description: String) = withContext(noParallelismDispatcher) {
        retrofitWebserviceApi.getEntries(description)
    }

    /**
     * This call should not be blocked by [getEntries] calls, but be executed shortly after it is called.
     */
    suspend fun getCategories() = withContext(dispatcher) {
        retrofitWebserviceApi.getCategories()
    }
}

完整的可执行 JVM 代码示例:github sample code - question branch

所以这里的想法是使用 Kotlin Coroutine Dispatchers 来限制并行请求。 但是,项目日志显示 OkHttp 使用自己的 OkHttp Dispatcher。

有没有办法停用 OkHttp Dispatcher 并在当前线程中运行网络调用(由 Coroutine Dispatcher 在这里定义)?

这是否可能而不会失去取消请求的可能性?

谢谢你的帮助!

    标签: kotlin retrofit kotlin-coroutines okhttp


    【解决方案1】:

    要使用另一个调度程序,我认为您需要删除 RetrofitWebserviceApi 中的 suspend 修饰符,以便将另一个调度程序用于以下功能:

    internal interface RetrofitWebserviceApi {
    
        @GET("entries")
        fun getEntries(@Query("description") description: String): EntriesResponse
    
        @GET("categories")
        fun getCategories(): CategoriesResponse
    }
    

    【讨论】:

      【解决方案2】:

      自定义调度程序可以设置为 OkhttpClient 如下

        private fun createDispatcher(): Dispatcher {
          val dispatcher = Dispatcher(Executors.newCachedThreadPool())
          dispatcher.maxRequests = 100
          dispatcher.maxRequestsPerHost = 100
          return dispatcher
        }
      
        private fun getOkHttpClient() = OkHttpClient.Builder()
          .addInterceptor(getLoggingInterceptor())
          .dispatcher(createDispatcher())
          .build()
      

      【讨论】:

        猜你喜欢
        • 2015-11-05
        • 2015-08-04
        • 2013-12-25
        • 1970-01-01
        • 1970-01-01
        • 2016-11-27
        • 1970-01-01
        • 2011-10-30
        • 2011-03-30
        相关资源
        最近更新 更多