Android:使用网络拦截器中的数据在不破坏体系结构的情况下完成与UI相关的工作

Android:使用网络拦截器中的数据在不破坏体系结构的情况下完成与UI相关的工作,android,kotlin,mvvm,kotlin-coroutines,Android,Kotlin,Mvvm,Kotlin Coroutines,有时,API可以在完成网络调用之前决定执行ui作业(例如,显示webview对话框)。这些标志位于响应头中,值通常是数据,如该webview的url 这是拦截器 override fun intercept(chain: Interceptor.Chain): Response { val response = chain.proceed(request) return when (response.code()) { 200 -&

有时,API可以在完成网络调用之前决定执行ui作业(例如,显示webview对话框)。这些标志位于响应头中,值通常是数据,如该webview的url

这是拦截器

    override fun intercept(chain: Interceptor.Chain): Response {
        val response = chain.proceed(request)
        return when (response.code()) {
            200 -> {
                response.headers().forEach { /* do something in ui layer if needed */}
                response;
            }
        }
    }

避免使用EventBus,因此我会将元数据对象添加到响应中,然后将其传递到存储库并在viewmodel中对其进行解析,并为
活动
片段
生成事件,但我们不知道何时触发此拦截,因此必须为每个api调用检查所有viewmodels中的所有类型的事件。

解决方案是在api结果中添加一个
InterceptionMetaData

data class InterceptionMetaData(
        val key: String,
        val data: String
)
将此数据类添加到响应(通常为成功类型,或者我们可以添加另一个截获的响应类型)

在我们的拦截器中,我们检查响应头(我在这里使用了所有头进行演示)

通常我们有基本视图模型,因此我们可以让我们的
BaseViewModel
构建一个事件,并将其传递给我们的
BaseFragment/BaseActivity
,以处理实际的ui作业(例如启动一个对话框)。该功能用于我放置
Log.d
的地方

when (this) {
  is Success -> success?.invoke(this.data, metaData)
  is Error -> error?.invoke(this.error)
  is Loading -> loading?.invoke()
  is Intercepted -> onIntercepted?.invoke(this.data, interceptionMetaDataList)
}
val interceptionMetaDataList: List<InterceptionMetaData> = response.headers().run {
  names().map { key ->
    get(key)?.let { InterceptionMetaData(key, it) }
  }
}.filterNotNull()
repository.getNewsList().collectResult(
  onIntercepted = { data, interceptionList ->
    Log.d(NewsViewModel::class.java.simpleName, "getNewsList: $interceptionList")
  },
  success = { data ->
    hideProgress()
    handleData(data)
  },
  error = { error ->
    hideProgress()
    showNoData(error)
  },
  loading = {
    showProgress()
})