改造 API 呼叫接收 "HTTP FAILED: java.io.IOException: Canceled"
Retrofit API call receives "HTTP FAILED: java.io.IOException: Canceled"
无法弄清楚为什么会这样。 rx 回调(onCompleted()、onError()、onNext())中的任何一个都不会被我的调用触发。我唯一收到的是这个 okhttp 输出:
D/OkHttp: --> GET https://api.privatbank.ua/p24api/exchange_rates?json=true&date=20.11.2016 http/1.1
D/OkHttp: --> END GET
D/OkHttp: <-- HTTP FAILED: java.io.IOException: Canceled
改造模块:
@Module
public class RestModule {
@Provides
@Singleton
public HttpLoggingInterceptor providesHttpLogginInterceptor() {
return new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
}
@Provides
@Singleton
public OkHttpClient providesOkHttpClient(@NonNull HttpLoggingInterceptor loggingInterceptor) {
return new OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.connectTimeout(ConstantsManager.CONNECTION_TIME_OUT, TimeUnit.SECONDS)
.readTimeout(ConstantsManager.READ_TIME_OUT, TimeUnit.SECONDS)
.build();
}
@Provides
@Singleton
public Gson providesGson() {
return new GsonBuilder().create();
}
@Provides
@Singleton
public Retrofit providesRetrofit(@NonNull OkHttpClient okHttpClient, @NonNull Gson gson) {
return new Retrofit.Builder()
.baseUrl(ConstantsManager.BASE_URL)
.client(okHttpClient)
.addConverterFactory(SimpleXmlConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
}
@Provides
@Singleton
public PrivatbankApi providesPrivatbankApi(@NonNull Retrofit retrofit) {
return retrofit.create(PrivatbankApi.class);
}
}
API 界面:
public interface PrivatbankApi {
@GET
Observable<CurrentRates> loadCurrentRates(@NonNull @Url String url);
@GET("exchange_rates")
Observable<DateRates> loadDateRates(@NonNull @Query("json") Boolean json, @NonNull @Query("date") String date);
}
订阅:
subscription = dataManager.loadDateRates(date)
.subscribeOn(Schedulers.io())
.doAfterTerminate(() -> {
})
.subscribe(dateRates -> {
// My code here...
}, throwable -> {
Timber.e(throwable, "Error while loading data occurred!");
});
顺便说一句,这两个调用得到相同的错误:
D/OkHttp: --> GET https://privat24.privatbank.ua/p24/accountorder?oper=prp&PUREXML&apicour&country=ua http/1.1
D/OkHttp: --> END GET
D/OkHttp: <-- HTTP FAILED: java.io.IOException: Canceled
D/OkHttp: --> GET https://api.privatbank.ua/p24api/exchange_rates?json=true&date=20.11.2016 http/1.1
D/OkHttp: --> END GET
D/OkHttp: <-- HTTP FAILED: java.io.IOException: Canceled
如果用户取消请求,则会抛出该异常。使用 RxJavaCallAdapterFactory
时,如果订阅在调用完成之前取消订阅,就会发生这种情况。所以我想在你打电话后的某个时候你会做 subscription.unsubscribe()
取消底层请求。
感谢@Kiskae。这给了我正确的提示。在我的例子中,我使用了 CompositeSubscription 并在它被另一种方法取消订阅后添加了订阅。
/**
* Adds a new {@link Subscription} to this {@code CompositeSubscription} if the
* {@code CompositeSubscription} is not yet unsubscribed. If the {@code CompositeSubscription} <em>is</em>
* unsubscribed, {@code add} will indicate this by explicitly unsubscribing the new {@code Subscription} as
* well.
*
* @param s
* the {@link Subscription} to add
*/
对我有帮助的是替换已弃用的调用适配器:
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
与:
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
这帮助我解决了这个问题,我每次都会调用 onError() 。
有关此的更多信息:https://github.com/JakeWharton/retrofit2-rxjava2-adapter
我遇到了同样的问题,但在我的情况下,当两个请求在同一个 CompositeDisposable
中订阅时,其中一个被取消。我的意思是这 2 个请求是并行完成的。
我的解决方案:我只定义了两个不同的订阅频道。
使用 Kotlin 协程我遇到了同样的异常。首先,我关闭了 ViewModel
(和一个对话框),然后使用 HTTP 请求启动了 Job
。在这种情况下协程被取消:kotlinx.coroutines.JobCancellationException: Job was cancelled; job=SupervisorJobImpl{Cancelling}.
close()
modelScope.launch {
val response = withContext(Dispatchers.IO) {
...
}
response?.let { ... }
}
然后我将 ViewModel
关闭到请求的末尾。
无法弄清楚为什么会这样。 rx 回调(onCompleted()、onError()、onNext())中的任何一个都不会被我的调用触发。我唯一收到的是这个 okhttp 输出:
D/OkHttp: --> GET https://api.privatbank.ua/p24api/exchange_rates?json=true&date=20.11.2016 http/1.1
D/OkHttp: --> END GET
D/OkHttp: <-- HTTP FAILED: java.io.IOException: Canceled
改造模块:
@Module
public class RestModule {
@Provides
@Singleton
public HttpLoggingInterceptor providesHttpLogginInterceptor() {
return new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY);
}
@Provides
@Singleton
public OkHttpClient providesOkHttpClient(@NonNull HttpLoggingInterceptor loggingInterceptor) {
return new OkHttpClient.Builder()
.addInterceptor(loggingInterceptor)
.connectTimeout(ConstantsManager.CONNECTION_TIME_OUT, TimeUnit.SECONDS)
.readTimeout(ConstantsManager.READ_TIME_OUT, TimeUnit.SECONDS)
.build();
}
@Provides
@Singleton
public Gson providesGson() {
return new GsonBuilder().create();
}
@Provides
@Singleton
public Retrofit providesRetrofit(@NonNull OkHttpClient okHttpClient, @NonNull Gson gson) {
return new Retrofit.Builder()
.baseUrl(ConstantsManager.BASE_URL)
.client(okHttpClient)
.addConverterFactory(SimpleXmlConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
}
@Provides
@Singleton
public PrivatbankApi providesPrivatbankApi(@NonNull Retrofit retrofit) {
return retrofit.create(PrivatbankApi.class);
}
}
API 界面:
public interface PrivatbankApi {
@GET
Observable<CurrentRates> loadCurrentRates(@NonNull @Url String url);
@GET("exchange_rates")
Observable<DateRates> loadDateRates(@NonNull @Query("json") Boolean json, @NonNull @Query("date") String date);
}
订阅:
subscription = dataManager.loadDateRates(date)
.subscribeOn(Schedulers.io())
.doAfterTerminate(() -> {
})
.subscribe(dateRates -> {
// My code here...
}, throwable -> {
Timber.e(throwable, "Error while loading data occurred!");
});
顺便说一句,这两个调用得到相同的错误:
D/OkHttp: --> GET https://privat24.privatbank.ua/p24/accountorder?oper=prp&PUREXML&apicour&country=ua http/1.1
D/OkHttp: --> END GET
D/OkHttp: <-- HTTP FAILED: java.io.IOException: Canceled
D/OkHttp: --> GET https://api.privatbank.ua/p24api/exchange_rates?json=true&date=20.11.2016 http/1.1
D/OkHttp: --> END GET
D/OkHttp: <-- HTTP FAILED: java.io.IOException: Canceled
如果用户取消请求,则会抛出该异常。使用 RxJavaCallAdapterFactory
时,如果订阅在调用完成之前取消订阅,就会发生这种情况。所以我想在你打电话后的某个时候你会做 subscription.unsubscribe()
取消底层请求。
感谢@Kiskae。这给了我正确的提示。在我的例子中,我使用了 CompositeSubscription 并在它被另一种方法取消订阅后添加了订阅。
/**
* Adds a new {@link Subscription} to this {@code CompositeSubscription} if the
* {@code CompositeSubscription} is not yet unsubscribed. If the {@code CompositeSubscription} <em>is</em>
* unsubscribed, {@code add} will indicate this by explicitly unsubscribing the new {@code Subscription} as
* well.
*
* @param s
* the {@link Subscription} to add
*/
对我有帮助的是替换已弃用的调用适配器:
implementation 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0'
与:
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.9.0'
这帮助我解决了这个问题,我每次都会调用 onError() 。 有关此的更多信息:https://github.com/JakeWharton/retrofit2-rxjava2-adapter
我遇到了同样的问题,但在我的情况下,当两个请求在同一个 CompositeDisposable
中订阅时,其中一个被取消。我的意思是这 2 个请求是并行完成的。
我的解决方案:我只定义了两个不同的订阅频道。
使用 Kotlin 协程我遇到了同样的异常。首先,我关闭了 ViewModel
(和一个对话框),然后使用 HTTP 请求启动了 Job
。在这种情况下协程被取消:kotlinx.coroutines.JobCancellationException: Job was cancelled; job=SupervisorJobImpl{Cancelling}.
close()
modelScope.launch {
val response = withContext(Dispatchers.IO) {
...
}
response?.let { ... }
}
然后我将 ViewModel
关闭到请求的末尾。