Следующее AsyncCall
- это то, что я сейчас использую (вдохновлено решением Дэвида Тинкера). Вместо повторных попыток ожидается, что для некоторых вызовов RPC потребуется много времени, и отобразится индикатор загрузки, если вызов не был возвращен до истечения указанного времени ожидания.
AsyncCall
также отслеживает количество вызовов RPC, которые выполняются в данный момент, и скрывает индикатор загрузки только в том случае, если все вызовы RPC вернулись. С помощью решения Дэвида индикатор загрузки может быть скрыт при более раннем возврате вызова RPC, даже если еще выполняется другой вызов. Это если в курсе предполагается, что виджет индикатора загрузки является глобальным для приложения, как в моем случае.
public abstract class AsyncCall<T> {
private static final int LOADING_TOLERANCE_MS = 100;
private static int loadingIndicatorCount = 0;
private Timer timer;
private boolean incremented;
private boolean displayFailure;
public AsyncCall(boolean displayFailure) {
this.displayFailure = displayFailure;
timer = new Timer() {
@Override
public void run() {
if (loadingIndicator++ == 0)
// show global loading widget here
incremented = true;
}
};
timer.schedule(LOADING_TOLERANCE_MS);
call(new AsyncCallback<T>() {
@Override
public void onSuccess(T result) {
timer.cancel();
if (incremented && --loadingIndicatorCount == 0)
// hide global loading widget here
callback(result);
}
@Override
public void onFailure(Throwable caught) {
timer.cancel();
if (incremented && --loadingIndicatorCount == 0)
// hide global loading widget here
if (AsyncCall.this.displayFailure)
// show error to user here
}
});
protected abstract void call(AsyncCallback<T> cb);
protected void callback(T result) {
// might just be a void result or a result we
// wish to ignore, so do not force implementation
// by declaring as abstract
}
}