在页面请求数据时,多数情况需要在页面退出时检查请求是否响应完成,如果没有响应或正在请求中,这时就需要将这些请求cancel掉。
比较方便的方式是,在页面基类中统一管理Retrofit Call,在页面onDestroy*的时候批量cancel掉当前页面中发起的所有请求Call。
定义页面请求Flag
public interface Questioner {
String giveRequestId();
}
/**
* 创建网络请求
* @param questioner questioner
* @param params Request Params
* @param <T> Result
* @return Call
*/
public <S,T> Call<T> createRequestCall(Questioner questioner, Class<S> SERVICE, String apiName, String[] params) {
final String requestId = questioner.giveRequestId();
final Class[] cPs = new Class[params == null ? 0 : params.length];
for (int i = 0; i < cPs.length; i++) {
cPs[i] = String.class;
}
try {
Method method = SERVICE.getDeclaredMethod(apiName, cPs);
S service = mRetrofit.create(SERVICE);
Object[] oPs = new Object[params == null ? 0 : params.length];
if (params != null) System.arraycopy(params, 0, oPs, 0, oPs.length);
final Call<T> rawCall = (Call<T>) method.invoke(service, oPs);
synchronized (mRequestSync) {
List<Call<?>> requests = mRequestMap.get(requestId);
if (requests == null) requests = new LinkedList<>();
requests.add(rawCall);
mRequestMap.put(requestId, requests);
}
return rawCall;
} catch (NoSuchMethodException e) {
return null;
} catch (InvocationTargetException | IllegalAccessException e) {
return null;
}
}
/**
* 请求网络数据
* @param questioner questioner
* @param params Request Params
* @param <T> Result
* @return Call
*/
public <S,T> Call<T> request(Questioner questioner, Class<S> SERVICE, String apiName, String[] params, final DataCallback<T> callback) {
final Questioner fQuestioner = questioner;
final Call<T> rawCall = createRequestCall(questioner, SERVICE, apiName, params);
final Handler uiHandler = new Handler(Looper.getMainLooper());
uiHandler.post(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onRequest(rawCall);
}
}
});
if (rawCall != null) {
rawCall.enqueue(new Callback<T>() {
@Override
public void onResponse(final Call<T> call, final Response<T> response) {
uiHandler.post(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onResponse(call, response.body());
}
}
});
removeCall(fQuestioner, rawCall);
}
@Override
public void onFailure(final Call<T> call, final Throwable throwable) {
uiHandler.post(new Runnable() {
@Override
public void run() {
if (callback != null) {
callback.onFailure(call, throwable);
}
}
});
removeCall(fQuestioner, rawCall);
}
});
}
return rawCall;
}
发起请求只需要如下操作
request(DemoApi.class, "test" /*DemoApi中定义的方法名称*/, new String[]{""} /*方法的参数String数组*/, new DataCallback<TestResult>() {
@Override
public void onRequest(Call<TestResult> call) {
}
@Override
public void onResponse(Call<TestResult> call, @Nullable TestResult result) {
}
@Override
public void onFailure(Call<TestResult> call, Throwable t) {
}
});
取消请求 - 这个方法可以在实现了Questioner接口的Activity销毁时统一调用,业务逻辑中只发起请求即可,不必单独取消某个网络请求
/**
* 取消给定Questioner的所有网络请求
* @param questioner questioner
*/
public void cancel(Questioner questioner) {
final String requestId = questioner.giveRequestId();
synchronized (mRequestSync) {
List<Call<?>> requests = mRequestMap.get(requestId);
if (requests != null) {
for (int i = 0; i < requests.size(); i++) {
Call<?> call = requests.get(i);
if (!call.isExecuted() && !call.isCanceled()) {
call.cancel();
}
}
}
mRequestMap.remove(requestId);
}
}