Rah*_*sia 8 android retrofit2 okhttp3
我正在尝试解决一个问题,我将进行几个异步调用,并根据原始请求,我正在执行一项任务.为了解决这个问题,我正在尝试为每个请求添加一个TAG,然后成功响应,我可以获取标记并根据标记采取行动.在这里,我只使用TAG来识别原始请求.
问题
在调用enqueue方法之前,我将标记设置为原始请求.但是当我在成功的回调中得到响应时,我得到的是我没有设置的不同标签.不知何故,请求对象本身就是那里的标记对象.我不确定,怎么样?
请检查以下代码 -
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());
}
});
Run Code Online (Sandbox Code Playgroud)
有人可以指出我在这里做错了什么.任何帮助,将不胜感激.
该解决方案显然是一种hack,但它可以工作。
假设您像这样创建Retrofit服务:
public <S> S createService(Class<S> serviceClass) {
// Could be a simple "new"
Retrofit.Builder retrofitBuilder = getRetrofitBuilder(baseUrl);
// Could be a simple "new"
OkHttpClient.Builder httpClientBuilder = getOkHttpClientBuilder();
// Build your OkHttp client
OkHttpClient httpClient = httpClientBuilder.build();
Retrofit retrofit = retrofitBuilder.client(httpClient).build();
return retrofit.create(serviceClass);
}
Run Code Online (Sandbox Code Playgroud)
您将需要向CallFactoryRetrofit实例添加一个新实例,因此它每次都会添加一个标签。由于标记是只读的,因此我们将使用仅包含一个元素的Object数组,稍后您将可以对其进行更改。
Retrofit retrofit = retrofitBuilder.client(httpClient).callFactory(new Call.Factory() {
@Override
public Call newCall(Request request) {
request = request.newBuilder().tag(new Object[]{null}).build();
Call call = httpClient.newCall(request);
// We set the element to the call, to (at least) keep some consistency
// If you want to only have Strings, create a String array and put the default value to null;
((Object[])request.tag())[0] = call;
return call;
}
}).build();
Run Code Online (Sandbox Code Playgroud)
现在,在创建呼叫之后,您将能够更改标签的内容:
((Object[])call.request().tag())[0] = "hello";
Run Code Online (Sandbox Code Playgroud)
对我来说,这段代码正在工作
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())
}
}
Run Code Online (Sandbox Code Playgroud)
然后按标签取消
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")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3147 次 |
| 最近记录: |