万事须己运,他得非我贤。这篇文章主要讲述Android OkHttp + Retrofit 取消请求的方法相关的知识,希望能为你提供帮助。
本文链接
前言在某一个界面,用户发起了一个网络请求,因为某种原因用户在网络请求完成前离开了当前界面,比较好的做法是取消这个网络请求。对于OkHttp来说,具体是调用Call
的cancel
方法。
如何找到这一个网络请求并取消掉它呢?
操作大致分为3步。第一步,在建立请求时,给请求(request)添加标记;第二步,根据标记,找到请求;最后,取消这个请求。
OkHttp中的tag要取消一个请求,OkHttp中可以使用cancel方法,参考。
OkHttp的request对象有tag。可以根据tag来标示请求。参考Stack Overflow。
//Set tags for your requests when you build them:
Request request = new Request.Builder().
url(url).tag("
requestKey"
).build();
//When you want to cancel:
//A) go through the queued calls and cancel if the tag matches:
for (Call call : mHttpClient.dispatcher().queuedCalls()) {
if (call.request().tag().equals("
requestKey"
))
call.cancel();
}//B) go through the running calls and cancel if the tag matches:
for (Call call : mHttpClient.dispatcher().runningCalls()) {
if (call.request().tag().equals("
requestKey"
))
call.cancel();
}
Retrofit中并没有显示地提供取消请求的接口。2018年时Retrofit仍未提供直接访问call对象的方法
那么如何找到目标网络请求呢?
Retrofit加入自定义header给每个与页面(Activity,Fragment)相关的request加入自定义header,参考。
给OkHttpClient添加拦截器。标记出页面的生存状态。如果页面销毁了,则取消对应的request。
以GithubOnandroid项目为例,https://github.com/RustFisher/GithubOnAndroid
添加标记持有一个ConcurrentHashMap< String, Boolean> 来标记页面存活状态。
private static ConcurrentHashMap<
String, Boolean>
actLiveMap = new ConcurrentHashMap<
>
();
// 标记Activity是否存活public static void markPageAlive(String actName) {
actLiveMap.put(actName, true);
}public static void markPageDestroy(String actName) {
actLiveMap.put(actName, false);
}
Activity中登记界面状态给当前Activity起名字。每个Activity的标记名必须唯一。
private static final String MY_ACT_NAME = "
xxx1Activity"
;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
NetworkCenter.markPageAlive(MY_ACT_NAME);
// ...
}@Override
protected void onDestroy() {
super.onDestroy();
NetworkCenter.markPageDestroy(MY_ACT_NAME);
// ...
}
OkHttpClient添加拦截器给OkHttpClient添加拦截器,在拦截器中检查页面的存活情况。
检查后,把这个自定义header移除掉。
public static final String HEADER_ACT_NAME = "
Activity-Name"
;
// 标记Activity界面名字private Interceptor lifeInterceptor = new Interceptor() {
@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
String actName = request.header(HEADER_ACT_NAME);
if (!TextUtils.isEmpty(actName)) {
Log.d(TAG, "
lifeInterceptor: actName: "
+ actName);
Boolean actLive = actLiveMap.get(actName);
if (actLive == null || !actLive) {
chain.call().cancel();
Log.d(TAG, "
lifeInterceptor: 取消请求, actName: "
+ actName);
} else {
Log.d(TAG, "
lifeInterceptor: 发起请求, actName: "
+ actName);
}
}
Request newRequest = request.newBuilder().removeHeader(HEADER_ACT_NAME).build();
return chain.proceed(newRequest);
}
};
OkHttpClient = new OkHttpClient.Builder()
.readTimeout(10, TimeUnit.SECONDS)
.connectTimeout(10, TimeUnit.SECONDS)
.addInterceptor(lifeInterceptor) // 添加拦截器
.build();
【Android OkHttp + Retrofit 取消请求的方法】call.cancel()后,不会再走Retrofit的subscribe方法。
添加header
@GET("
users/{owner}/repos"
)
Observable<
List<
UserRepo>
>
userRepo(
@Header(NetworkCenter.HEADER_ACT_NAME) @Nullable String actName,
@Path("
owner"
) String owner,
@Query("
sort"
) String sortType);
推荐阅读
- Android OkHttp, 一行代码 OkHttp提升请求稳定性
- 关于Sketch中的版式可能不知道的事情
- Web和印刷设计的字体样式
- 拟态,平面设计和字体设计的兴起
- 使用这些顶级UX工具掌握你的手艺
- 形式和功能–顶级线框工具指南
- 将可用性测试数据变成行动而不会发疯
- 所有趋势都值得吗( Web设计人员最常犯的5个错误)
- 体验就是一切–终极用户体验指南