在頁面請求數(shù)據(jù)時涝动,多數(shù)情況需要在頁面退出時檢查請求是否響應(yīng)完成狸吞,如果沒有響應(yīng)或正在請求中融撞,這時就需要將這些請求cancel掉盼铁。
比較方便的方式是,在頁面基類中統(tǒng)一管理Retrofit Call尝偎,在頁面onDestroy*的時候批量cancel掉當(dāng)前頁面中發(fā)起的所有請求Call饶火。
定義頁面請求Flag
public interface Questioner {
String giveRequestId();
}
/**
* 創(chuàng)建網(wǎng)絡(luò)請求
* @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;
}
}
/**
* 請求網(wǎng)絡(luò)數(shù)據(jù)
* @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;
}
發(fā)起請求只需要如下操作
request(DemoApi.class, "test" /*DemoApi中定義的方法名稱*/, new String[]{""} /*方法的參數(shù)String數(shù)組*/, 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) {
}
});
取消請求 - 這個方法可以在實現(xiàn)了Questioner接口的Activity銷毀時統(tǒng)一調(diào)用,業(yè)務(wù)邏輯中只發(fā)起請求即可致扯,不必單獨取消某個網(wǎng)絡(luò)請求
/**
* 取消給定Questioner的所有網(wǎng)絡(luò)請求
* @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);
}
}