android - Retrofit 在原请求对象上添加标签

标签 android retrofit2 okhttp

我正在尝试解决一个问题,我将进行几个异步调用并根据原始请求执行一项任务。为了解决这个问题,我试图为每个请求添加一个标签,然后在成功响应时,我可以获得标签并根据标签采取行动。在这里,我仅使用 TAG 来识别原始请求。

问题

在调用入队方法之​​前,我将标记设置为原始请求。但是当我在成功的回调中得到响应时,我得到了我没有设置的不同标签。请求对象本身以某种方式作为标记对象出现。我不确定,如何???

请检查下面的代码-

GitHubService gitHubService = GitHubService.retrofit.create(GitHubService.class);
                final Call<List<Contributor>> call = gitHubService.repoContributors("square", "retrofit");

                // Set the string tag to the original request object.
                call.request().newBuilder().tag("hello").build();


                call.enqueue(new Callback<List<Contributor>>() {
                    @Override
                    public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>> response) {
                        Log.d("tag", response.raw().request().tag().toString());
                        // I'm getting Request{method=GET, url=https://api.github.com/repos/square/retrofit/contributors, tag=null} as the value of the tag. WHY????
                        final TextView textView = (TextView) findViewById(R.id.textView);
                        textView.setText(response.body().toString());
                    }
                    @Override
                    public void onFailure(Call<List<Contributor>> call, Throwable t) {
                        final TextView textView = (TextView) findViewById(R.id.textView);
                        textView.setText("Something went wrong: " + t.getMessage());
                    }
                });

有人能指出我到底做错了什么吗?任何帮助,将不胜感激。

最佳答案

对我来说这段代码是有效的

val CLIENT: OkHttpClient = OkHttpClient.Builder().apply {
    addInterceptor(TagInterceptor())
}.build()

val SERVER_API: ServerApi = Retrofit.Builder()
    .client(CLIENT)
    .baseUrl(BASE_URL)
    .build()
    .create(ServerApi::class.java)

interface ServerApi {

    @GET("api/notifications")
    @Tag("notifications")
    suspend fun getNotifications(): ResponseBody
}

@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER)
@Retention(AnnotationRetention.RUNTIME)
annotation class Tag(val value: String)

internal class TagInterceptor : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()
        val builder = request.newBuilder()
        request.tag(Invocation::class.java)?.let {
            it.method().getAnnotation(Tag::class.java)?.let { tag ->
                builder.tag(tag.value)
            }
        }
        return chain.proceed(builder.build())
    }
}

然后通过标签取消

fun OkHttpClient.cancelAll(tag: String) {
    for (call in dispatcher().queuedCalls()) {
        if (tag == call.request().tag()) {
            call.cancel()
        }
    }
    for (call in dispatcher().runningCalls()) {
        if (tag == call.request().tag()) {
            call.cancel()
        }
    }
}

CLIENT.cancelAll("notifications")

关于android - Retrofit 在原请求对象上添加标签,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42066885/

相关文章:

java - 根据情况启用或禁用按钮的最佳方法

java - 我应该如何处理服务器超时和对 Android 应用程序中的 http 帖子的错误代码响应?

android - 使用 Retrofit 2 添加一个数组作为请求参数

android - 在 RoboSpice 中仅将 TLS 与 Retrofit 结合使用

java - 需要测试静态Utils类

android - 要为 Android Activity 设置半透明背景?

junit - 如何使用 MockWebServer 验证 POST 正文的内容?

android - 如何在 Android 中实现 webhook?

java - 当我尝试记录网络响应时,OKHttp 抛出非法状态异常

okhttp - 如何获取 http2 客户端(如 okhttp 或 java 11 httpclient)中的 Max_concurrent_streams 数量和流 id