XUtils3代碼詳解--http

這是xutils3 源碼分析的第二篇幽告。

第一篇超級(jí)傳送門:xutils3詳解一


官方訪問網(wǎng)絡(luò)用法:

復(fù)雜版本:

/** 
* 自定義實(shí)體參數(shù)類請參考: 
* 請求注解 {@link org.xutils.http.annotation.HttpRequest} 
* 請求注解處理模板接口 {@link org.xutils.http.app.ParamsBuilder} 
* * 需要自定義類型作為callback的泛型時(shí), 參考: 
* 響應(yīng)注解 {@link org.xutils.http.annotation.HttpResponse} 
* 響應(yīng)注解處理模板接口 {@link org.xutils.http.app.ResponseParser} 
* * 示例: 查看 org.xutils.sample.http 包里的代碼 
*/
BaiduParams params =newBaiduParams();
params.wd ="xUtils";// 有上傳文件時(shí)使用multipart表單, 否則上傳原始文件流.
// params.setMultipart(true);// 上傳文件方式 1
// params.uploadFile = new File("/sdcard/test.txt");// 上傳文件方式 2
// params.addBodyParameter("uploadFile", new File("/sdcard/test.txt"));
Callback.Cancelable cancelable = x.http().get(params, 
/** * 1. callback的泛型: 
* callback參數(shù)默認(rèn)支持的泛型類型參見{@link org.xutils.http.loader.LoaderFactory}, 
* 例如: 指定泛型為File則可實(shí)現(xiàn)文件下載, 使用params.setSaveFilePath(path)指定文件保存的全路徑. 
* 默認(rèn)支持?jǐn)帱c(diǎn)續(xù)傳(采用了文件鎖和尾端校驗(yàn)續(xù)傳文件的一致性). 
* 其他常用類型可以自己在LoaderFactory中注冊, 
* 也可以使用{@link org.xutils.http.annotation.HttpResponse} 
* 將注解HttpResponse加到自定義返回值類型上, 實(shí)現(xiàn)自定義ResponseParser接口來統(tǒng)一轉(zhuǎn)換. 
* 如果返回值是json形式, 那么利用第三方的json工具將十分容易定義自己的ResponseParser. 
* 如示例代碼{@link org.xutils.sample.http.BaiduResponse}, 可直接使用BaiduResponse作為 
* callback的泛型. 
* * 2. callback的組合: 
* 可以用基類或接口組合個(gè)種類的Callback, 見{@link org.xutils.common.Callback}. 
* 例如: 
* a. 組合使用CacheCallback將使請求檢測緩存或?qū)⒔Y(jié)果存入緩存(僅GET請求生效). 
* b. 組合使用PrepareCallback的prepare方法將為callback提供一次后臺(tái)執(zhí)行耗時(shí)任務(wù)的機(jī)會(huì), 
* 然后將結(jié)果給onCache或onSuccess. 
* c. 組合使用ProgressCallback將提供進(jìn)度回調(diào).
* ...(可參考{@link org.xutils.image.ImageLoader} 
* 或 示例代碼中的 {@link org.xutils.sample.download.DownloadCallback}) 
* * 3. 請求過程攔截或記錄日志: 參考 {@link org.xutils.http.app.RequestTracker} 
* * 4. 請求Header獲取: 參考 {@link org.xutils.http.app.RequestInterceptListener} 
* * 5. 其他(線程池, 超時(shí), 重定向, 重試, 代理等): 參考 {@link org.xutils.http.RequestParams} 
* 
**/
  newCallback.CommonCallback<String>() { 
      @Override
      public void onSuccess(Stringresult) { 
        Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show(); 
      } 
      @Override
      public void onError(Throwableex, booleanisOnCallback) { 
          //Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();
          if (ex instanceofHttpException) { // 網(wǎng)絡(luò)錯(cuò)誤
              HttpException httpEx = (HttpException) ex; 
              int responseCode = httpEx.getCode(); 
              String responseMsg = httpEx.getMessage();
               String errorResult = httpEx.getResult();
               // ... 
          } else {
           // 其他錯(cuò)誤//
             ... 
          } 
          Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show(); 
        } 
        @Override
        public void onCancelled(CancelledExceptioncex) { 
            Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show();
           }
     @Override
      public void onFinished() { } 
    });
// cancelable.cancel(); // 取消請求

簡單版本:

RequestParams params =newRequestParams("https://www.baidu.com/s"); 
params.setSslSocketFactory(...); // 設(shè)置ssl 
params.addQueryStringParameter("wd", "xUtils"); 
x.http().get(params, newCallback.CommonCallback<String>() { 
  @Override
  public void onSuccess(Stringresult) { 
  Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show(); 
  } 
  @Override
  public void onError(Throwableex, booleanisOnCallback) { 
  Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();
  } 
  @Override
  public void onCancelled(CancelledExceptioncex) { 
  Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show(); 
  } 
  @Override
  public void onFinished() { }
 });
帶有緩存的請求示例:
BaiduParams params =newBaiduParams();
params.wd ="xUtils";
// 默認(rèn)緩存存活時(shí)間, 單位:毫秒.(如果服務(wù)沒有返回有效的max-age或Expires)params.setCacheMaxAge(1000*60);
Callback.Cancelable cancelable // 使用CacheCallback, xUtils將為該請求緩存數(shù)據(jù).
          = x.http().get(params, newCallback.CacheCallback<String>() { 
          privateboolean hasError =false;
          privateString result =null; 
          @Override
          public boolean onCache(Stringresult) {
           // 得到緩存數(shù)據(jù), 緩存過期后不會(huì)進(jìn)入這個(gè)方法.
          // 如果服務(wù)端沒有返回過期時(shí)間, 參考params.setCacheMaxAge(maxAge)方法.
           ////* 客戶端會(huì)根據(jù)服務(wù)端返回的 header 中 max-age 或 expires 來確定本地緩存是否給 onCache 方法.
          // 如果服務(wù)端沒有返回 max-age 或 expires, 那么緩存將一直保存, 除非這里自己定義了返回false的
        // 邏輯, 那么xUtils將請求新數(shù)據(jù), 來覆蓋它.
        //// * 如果信任該緩存返回 true, 將不再請求網(wǎng)絡(luò);
        // 返回 false 繼續(xù)請求網(wǎng)絡(luò), 但會(huì)在請求頭中加上ETag, Last-Modified等信息,
        // 如果服務(wù)端返回304, 則表示數(shù)據(jù)沒有更新, 不繼續(xù)加載數(shù)據(jù).
        //this.result = result; returnfalse;   
          // true: 信任緩存數(shù)據(jù), 不在發(fā)起網(wǎng)絡(luò)請求; false不信任緩存數(shù)據(jù).
        } 
        @Override
        public void onSuccess(Stringresult) { 
          // 注意: 如果服務(wù)返回304或 onCache 選擇了信任緩存, 這里將不會(huì)被調(diào)用,
          // 但是 onFinished 總會(huì)被調(diào)用.
          this.result = result; 
        } 
        @Override
        public void onError(Throwableex, booleanisOnCallback) {
         hasError =true;
         Toast.makeText(x.app(), ex.getMessage(), Toast.LENGTH_LONG).show();
         if (ex instanceofHttpException) {
             // 網(wǎng)絡(luò)錯(cuò)誤
            HttpException httpEx = (HttpException) ex;
             int responseCode = httpEx.getCode();
             String responseMsg = httpEx.getMessage();
             String errorResult = httpEx.getResult();
         // ... 
        } else {  
       // 其他錯(cuò)誤
        // ...
         }
     }
       @Override
        public void onCancelled(CancelledExceptioncex) {   
            Toast.makeText(x.app(), "cancelled", Toast.LENGTH_LONG).show();
        }
       @Override
        public void onFinished() {
             if (!hasError && result !=null) {
               // 成功獲取數(shù)據(jù)
              Toast.makeText(x.app(), result, Toast.LENGTH_LONG).show();
               }
         }
    });


源碼查看:

首先還是入口:http相關(guān)的接口和實(shí)現(xiàn)類纹坐。HttpManager和HttpManagerImpl
接口很簡單箫爷。定義了三個(gè)異步請求和四個(gè)同步請求的方法簽名酪劫。

/** 
* Created by wyouflf on 15/6/17. 
* http請求接口
*/
public interface HttpManager {
/** * 異步GET請求*/
<T> Callback.Cancelable get(RequestParams entity, Callback.CommonCallback<T> callback);
/** * 異步POST請求*/
<T> Callback.Cancelable post(RequestParams entity, Callback.CommonCallback<T> callback);
/** * 異步請求*/
<T> Callback.Cancelable request(HttpMethod method, RequestParams entity, Callback.CommonCallback<T> callback);
/** * 同步GET請求*/
<T> T getSync(RequestParams entity, Class<T> resultType) throws Throwable;
/** * 同步POST請求 */
<T> T postSync(RequestParams entity, Class<T> resultType) throws Throwable;
/** * 同步請求 */
<T> T requestSync(HttpMethod method, RequestParams entity, Class<T> resultType) throws Throwable;
/** * 同步請求 */
<T> T requestSync(HttpMethod method, RequestParams entity, Callback.TypedCallback<T> callback) throws Throwable;
}

先看異步的一些實(shí)現(xiàn)方法:
HttpManagerImpl: 看源碼我們得知舀凛。異步請求最后都會(huì)調(diào)用到這個(gè)方法:request(···)扼仲。在這個(gè)方法中發(fā)現(xiàn) 會(huì)new一個(gè)HttpTask 并放到線程池中運(yùn)行远寸。在上一篇博客可以知道 x.task().start(task) 其實(shí)就是調(diào)用task的doBackground方法抄淑。

@Override
public <T> Callback.Cancelable request(HttpMethod method, RequestParams entity, Callback.CommonCallback<T> callback) { 
entity.setMethod(method);
Callback.Cancelable cancelable = null;
 if (callback instanceof Callback.Cancelable) {
 cancelable = (Callback.Cancelable) callback;
} 
HttpTask<T> task = new HttpTask<T>(entity, cancelable, callback); 
return x.task().start(task);
}

我們繼續(xù)跟進(jìn)來查看HttpTask:* 我們發(fā)現(xiàn)httpTask 中有哦很多成員變量。 作者代碼注釋的也比較清楚驰后。


/** 
* Created by wyouflf on 15/7/23. 
* http 請求任務(wù)
*/
public class HttpTask<ResultType> extends AbsTask<ResultType> implements ProgressHandler {// 請求相關(guān)
private RequestParams params;
private UriRequest request;
private RequestWorker requestWorker;
private final Executor executor;
private final Callback.CommonCallback<ResultType> callback;
// 緩存控制
private Object rawResult = null;
private final Object cacheLock = new Object();
private volatile Boolean trustCache = null;
// 擴(kuò)展callback
private Callback.CacheCallback<ResultType> cacheCallback;
private Callback.PrepareCallback prepareCallback;
private Callback.ProgressCallback progressCallback;
private RequestInterceptListener requestInterceptListener;
// 文件下載線程數(shù)限制
private Type loadType;
private final static int MAX_FILE_LOAD_WORKER = 3;
private final static AtomicInteger sCurrFileLoadCount = new AtomicInteger(0);
// 文件下載任務(wù)
private static final HashMap<String, WeakReference<HttpTask<?>>>DOWNLOAD_TASK = new HashMap<String, WeakReference<HttpTask<?>>>(1);
private static final PriorityExecutor HTTP_EXECUTOR = new PriorityExecutor(5, true);
private static final PriorityExecutor CACHE_EXECUTOR = new PriorityExecutor(5, true);
}
  • HttpTask構(gòu)造函數(shù)中,先用了兩個(gè)斷言來確保params 和callback 不為空肆资。并賦值給成員變量。 判斷是哪個(gè)callback 并賦值給想應(yīng)的callback灶芝。初始化tracker 日志跟蹤系統(tǒng)郑原。初始化線程池 executor.
public HttpTask(RequestParams params, Callback.Cancelable cancelHandler, Callback.CommonCallback<ResultType> callback) { 
super(cancelHandler);
 assert params != null;
 assert callback != null;
 // set params & callback
 this.params = params;
 this.callback = callback;
 if (callback instanceof Callback.CacheCallback) {
 this.cacheCallback = (Callback.CacheCallback<ResultType>) callback;
 } 
if (callback instanceof Callback.PrepareCallback) { 
this.prepareCallback = (Callback.PrepareCallback) callback;
 }
 if (callback instanceof Callback.ProgressCallback) { 
this.progressCallback = (Callback.ProgressCallback<ResultType>) callback; 
} 
if (callback instanceof RequestInterceptListener) { 
this.requestInterceptListener = (RequestInterceptListener) callback;
 } 
// init tracker {
 RequestTracker customTracker = params.getRequestTracker();
 if (customTracker == null) {
 if (callback instanceof RequestTracker) {
customTracker = (RequestTracker) callback;
 } else {
 customTracker = UriRequestFactory.getDefaultTracker();
 } 
}
 if (customTracker != null) {
 tracker = new RequestTrackerWrapper(customTracker);
 } 
}
 // init executor
 if (params.getExecutor() != null) {
 this.executor = params.getExecutor();
 } else { 
if (cacheCallback != null) {
 this.executor = CACHE_EXECUTOR;
} else { 
this.executor = HTTP_EXECUTOR;
 } 
}
}
  • doBackground 方法: 異步請求的最主要的方法。 我把這個(gè)方法截?cái)嗔恕?這部分主要是做一些準(zhǔn)備工作夜涕。比如說 初始化犯犁,緩存等。
@Override
@SuppressWarnings("unchecked")
protected ResultType doBackground() throws Throwable {
 if (this.isCancelled()) {
  throw new Callback.CancelledException("cancelled before request");
 }
 // 初始化請求參數(shù) 
 ResultType result = null; 
 resolveLoadType();
 request = createNewRequest();
 checkDownloadTask();
 // retry 初始化
 boolean retry = true;
 int retryCount = 0;
 Throwable exception = null;
 HttpRetryHandler retryHandler = this.params.getHttpRetryHandler();
 if (retryHandler == null) {
  retryHandler = new HttpRetryHandler();
  }
 retryHandler.setMaxRetryCount(this.params.getMaxRetryCount());
 if (this.isCancelled()) {
  throw new Callback.CancelledException("cancelled before request"); 
 } 
 // 檢查緩存
 Object cacheResult = null;
 if (cacheCallback != null && HttpMethod.permitsCache(params.getMethod())) { 
 // 嘗試從緩存獲取結(jié)果, 并為請求頭加入緩存控制參數(shù).
 try {
  clearRawResult(); LogUtil.d("load cache: " + this.request.getRequestUri());
 rawResult = this.request.loadResultFromCache();
  } catch (Throwable ex) {
  LogUtil.w("load disk cache error", ex);

 }
  if (this.isCancelled()) {
 clearRawResult();
 throw new Callback.CancelledException("cancelled before request");
 }
  if (rawResult != null) {
    if (prepareCallback != null) {
      try {
         cacheResult = prepareCallback.prepare(rawResult);
       } catch (Throwable ex) {
         cacheResult = null;
         LogUtil.w("prepare disk cache error", ex);
       } finally {
          clearRawResult();
       }
     } else {
     cacheResult = rawResult;   
  }
   if (this.isCancelled()) {
     throw new Callback.CancelledException("cancelled before request");
    } 
    if (cacheResult != null) {
       // 同步等待是否信任緩存
       this.update(FLAG_CACHE, cacheResult); 
        while (trustCache == null) {
             synchronized (cacheLock) {
                       try {
                                 cacheLock.wait();
                              } catch (Throwable ignored) {
                               }
             }
           } 
        // 處理完成 
      if (trustCache) {
             return null;
       }
     }
    }
  } 
  if (trustCache == null) {
       trustCache = false;
     } 
  if (cacheResult == null) {
     this.request.clearCacheHeader();
   }
  • 發(fā)請求的代碼: 請求代碼中主要就是重試機(jī)子和發(fā)送機(jī)制女器。字段retry 是控制重試的開關(guān)酸役。請求正常則retry一直為false。否則異常處理代碼塊里編寫有重試的規(guī)則驾胆。在代碼里面發(fā)送請求的是對象RequestWorker的run()涣澡;方法。所有我們?nèi)タ纯碦equestWorker對象丧诺。
 // 發(fā)起請求
 retry = true;
 while (retry) {
   retry = false;
   try {
       if (this.isCancelled()) {
         throw new Callback.CancelledException("cancelled before request");
         } 
      // 由loader發(fā)起請求, 拿到結(jié)果. 
      this.request.close(); 
      // retry 前關(guān)閉上次請求 
      try {
           clearRawResult();
           // 開始請求工作 
            LogUtil.d("load: " + this.request.getRequestUri()); 
            requestWorker = new RequestWorker();
           if (params.isCancelFast()) {
               requestWorker.start();
               requestWorker.join();
            } else {
            requestWorker.run();
           } 
          if (requestWorker.ex != null) {
                   throw requestWorker.ex;
          }
         rawResult = requestWorker.result;
         } catch (Throwable ex) {
           clearRawResult();
           if (this.isCancelled()) {
               throw new Callback.CancelledException("cancelled during request");
             } else {
           throw ex;
           }
       }
       if (prepareCallback != null) { 
          if (this.isCancelled()) { 
                  throw new Callback.CancelledException("cancelled before request");
           }
         try {
             result = (ResultType) prepareCallback.prepare(rawResult);
         } finally {
           clearRawResult();
         } 
        } else { 
          result = (ResultType) rawResult;
        }
         // 保存緩存 
        if (cacheCallback != null && HttpMethod.permitsCache(params.getMethod())) {
           this.request.save2Cache();
         }
        if (this.isCancelled()) { 
              throw new Callback.CancelledException("cancelled after request");
         }
       } catch (HttpRedirectException redirectEx) {
             retry = true;
              LogUtil.w("Http Redirect:" + params.getUri());
       } catch (Throwable ex) {
           if (this.request.getResponseCode() == 304) {
             // disk cache is valid.
             return null;
           } else {
           exception = ex;
           if (this.isCancelled() && !(exception instanceof Callback.CancelledException)) {
               exception = new Callback.CancelledException("canceled by user");
             }
           retry = retryHandler.retryRequest(exception, ++retryCount, this.request);
           }
          } 
        } 
      if (exception != null && result == null && !trustCache) {
             throw exception; 
      } 
      return result;
  }
  • RequestWorker: 是HttpTask的內(nèi)部類 入桂,主要的功能是請求發(fā)送和加載數(shù)據(jù)線程. 內(nèi)部run()方法分析:
    • 下載另作處理
    • 請求前回調(diào) requestInterceptListener.beforeRequest(request);
    • 請求 this.result = request.loadResult(); 得到結(jié)果
    • 請求后回調(diào) requestInterceptListener.afterRequest(request);
    • http重定向類的異常處理。
/** 
* 請求發(fā)送和加載數(shù)據(jù)線程. 
* 該線程被join到HttpTask的工作線程去執(zhí)行. 
* 它的主要作用是為了能強(qiáng)行中斷請求的鏈接過程; 
* 并輔助限制同時(shí)下載文件的線程數(shù). 
* but: 
* 創(chuàng)建一個(gè)Thread約耗時(shí)2毫秒, 優(yōu)化? 
*/
private final class RequestWorker extends Thread { 
 /*private*/ Object result;
 /*private*/ Throwable ex;
 private RequestWorker() { }
 public void run() { 
    try {
       if (File.class == loadType) {
           while (sCurrFileLoadCount.get() >= MAX_FILE_LOAD_WORKER && !HttpTask.this.isCancelled()) {
             synchronized (sCurrFileLoadCount) {
                 try {
                     sCurrFileLoadCount.wait(100);
                      } catch (Throwable ignored) { }
                 } 
              }
           sCurrFileLoadCount.incrementAndGet();
           }
         if (HttpTask.this.isCancelled()) {
               throw new Callback.CancelledException("cancelled before request");
           }
         // intercept response 
        if (requestInterceptListener != null) { 
              requestInterceptListener.beforeRequest(request);
         }
         try {
             this.result = request.loadResult();
           } catch (Throwable ex) {
               this.ex = ex;
           } 
        // intercept response
       if (requestInterceptListener != null) { 
              requestInterceptListener.afterRequest(request);
         }
       if (this.ex != null) {
             throw this.ex;
         } 
      } catch (Throwable ex) {
           this.ex = ex;
           if (ex instanceof HttpException) {
                 HttpException httpEx = (HttpException) ex;
                 int errorCode = httpEx.getCode();
                 if (errorCode == 301 || errorCode == 302) {
                       RedirectHandler redirectHandler = params.getRedirectHandler();
                       if (redirectHandler != null) {
                           try {
                                 RequestParams redirectParams = redirectHandler.getRedirectParams(request);
                                 if (redirectParams != null) {
                                   if (redirectParams.getMethod() == null) { 
                                        redirectParams.setMethod(params.getMethod());
                                     }
                                 // 開始重定向請求
                                 HttpTask.this.params = redirectParams;
                                 HttpTask.this.request = createNewRequest(); 
                                 this.ex = new HttpRedirectException(errorCode, httpEx.getMessage(), httpEx.getResult());
                               }
                               } catch (Throwable throwable) {
                                                    this.ex = ex; 
                               } 
                            } 
                          } 
                        } 
                      } finally {
                          if (File.class == loadType) {
                             synchronized (sCurrFileLoadCount) { 
                                          sCurrFileLoadCount.decrementAndGet();   
                                          sCurrFileLoadCount.notifyAll();
                               } 
                            }
                         } 
  }
}

同步的一些實(shí)現(xiàn)方法:

  • **HttpManagerImpl: ** 最終都會(huì)內(nèi)部調(diào)用到requestSync(···)的方法锅必。 在這個(gè)方法中 我們可以發(fā)現(xiàn) 事格。作者也創(chuàng)建了一個(gè)HttpTask。并調(diào)用了x.task().startSync(task);的方法搞隐。這個(gè)方法我們task的實(shí)現(xiàn)類發(fā)現(xiàn)實(shí)際調(diào)用的是 TaskControllerImpl.startSync( AbsTask<T> task)
Override 
public <T> T getSync(RequestParams entity, Class<T> resultType) throws Throwable {
   return requestSync(HttpMethod.GET, entity, resultType);
  }
@Override
 public <T> T postSync(RequestParams entity, Class<T> resultType) throws Throwable {
 return requestSync(HttpMethod.POST, entity, resultType);
}
@Override
public <T> T requestSync(HttpMethod method, RequestParams entity, Class<T> resultType) throws Throwable {
 DefaultSyncCallback<T> callback = new DefaultSyncCallback<T>(resultType);
 return requestSync(method, entity, callback);
}
@Override
public <T> T requestSync(HttpMethod method, RequestParams entity, Callback.TypedCallback<T> callback) throws Throwable { 
entity.setMethod(method);
 HttpTask<T> task = new HttpTask<T>(entity, null, callback);
 return x.task().startSync(task);
}

  • TaskControllerImpl.startSync( AbsTask<T> task) 找到這個(gè)方法我們發(fā)現(xiàn) 調(diào)用的是AbsTask的四個(gè)方法驹愚。onWaiting onStarted doBackground onSuccess 我們知道其實(shí)就是httpTask的這個(gè)四個(gè)方法。通過字面意思我們也可以知道就是 等待劣纲,開始逢捺,子線程運(yùn)行和成功四個(gè)方法。
@Override
public <T> T startSync(AbsTask<T> task) throws Throwable {
 T result = null;
 try {
   task.onWaiting();
   task.onStarted();
   result = task.doBackground();
   task.onSuccess(result);
   } catch (Callback.CancelledException cex) {
       task.onCancelled(cex);
   } catch (Throwable ex) { 
        task.onError(ex, false);
         throw ex;
   } finally {
       task.onFinished();
   }
 return result;
}
  • HttpTask的這四個(gè)方法: 在onSuccess方法中出現(xiàn)一個(gè)callback癞季〗偻回溯到TaskControllerImpl,我們發(fā)現(xiàn)了這個(gè)callback绷柒。它為外部傳遞的志于。外部沒有傳遞的化。有個(gè)默認(rèn)的DefaultSyncCallback废睦。
@Override
protected void onWaiting() { 
  if (tracker != null) {
     tracker.onWaiting(params);
   }
 if (progressCallback != null) {
     progressCallback.onWaiting();
   }
}
@Override
protected void onStarted() {
   if (tracker != null) {
     tracker.onStart(params);
   }
   if (progressCallback != null) {
       progressCallback.onStarted();
   }
}
@Override
protected void onSuccess(ResultType result) {
   if (tracker != null) {
       tracker.onSuccess(request, result);
    }
   if (result != null) {
     callback.onSuccess(result);
    }
}
  • DefaultSyncCallback: 此對象傳遞一個(gè)泛型伺绽。此泛型就為onSuccess 中返回的結(jié)果。 需要再構(gòu)建DefaultSyncCallback對象時(shí)候傳遞。
private class DefaultSyncCallback<T> implements Callback.TypedCallback<T> {
 private final Class<T> resultType;
 public DefaultSyncCallback(Class<T> resultType) {
 this.resultType = resultType;
 }
 @Override
 public Type getLoadType() {
   return resultType;
   }
 @Override
 public void onSuccess(T result) { }
 @Override
 public void onError(Throwable ex, boolean isOnCallback) { } 
@Override
 public void onCancelled(CancelledException cex) { }
 @Override
 public void onFinished() { }
}

從task的onwaiting 可以得到奈应。同步請求會(huì)一直等待 直到請求返回 或者請求超時(shí)澜掩。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市杖挣,隨后出現(xiàn)的幾起案子肩榕,更是在濱河造成了極大的恐慌,老刑警劉巖惩妇,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件株汉,死亡現(xiàn)場離奇詭異,居然都是意外死亡屿附,警方通過查閱死者的電腦和手機(jī)郎逃,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來挺份,“玉大人,你說我怎么就攤上這事贮懈≡炔矗” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵朵你,是天一觀的道長各聘。 經(jīng)常有香客問我,道長抡医,這世上最難降的妖魔是什么躲因? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮忌傻,結(jié)果婚禮上大脉,老公的妹妹穿的比我還像新娘。我一直安慰自己水孩,他們只是感情好镰矿,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著俘种,像睡著了一般秤标。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上宙刘,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天苍姜,我揣著相機(jī)與錄音,去河邊找鬼悬包。 笑死衙猪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播屈嗤,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼潘拨,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了饶号?” 一聲冷哼從身側(cè)響起铁追,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎茫船,沒想到半個(gè)月后琅束,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡算谈,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年涩禀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片然眼。...
    茶點(diǎn)故事閱讀 39,992評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡艾船,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出高每,到底是詐尸還是另有隱情屿岂,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布鲸匿,位于F島的核電站爷怀,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏带欢。R本人自食惡果不足惜运授,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望乔煞。 院中可真熱鬧吁朦,春花似錦、人聲如沸瘤缩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽剥啤。三九已至锦溪,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間府怯,已是汗流浹背刻诊。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牺丙,地道東北人则涯。 一個(gè)月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓复局,卻偏偏與公主長得像,于是被迫代替她去往敵國和親粟判。 傳聞我的和親對象是個(gè)殘疾皇子亿昏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Xutils3.0技術(shù)分享1.這個(gè)技術(shù)分享的目的1.首先要讓大家了解Xutil3.0是什么Xtuils3.0的前身...
    wodezhuanshu閱讀 3,116評論 5 9
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)档礁,斷路器角钩,智...
    卡卡羅2017閱讀 134,657評論 18 139
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法呻澜,內(nèi)部類的語法递礼,繼承相關(guān)的語法,異常的語法羹幸,線程的語...
    子非魚_t_閱讀 31,632評論 18 399
  • RPC框架遠(yuǎn)程調(diào)用的實(shí)現(xiàn)方式在原理上是比較簡單的脊髓,即將調(diào)用的方法(接口名、方法名栅受、參數(shù)類型将硝、參數(shù))序列化之后發(fā)送到...
    謎碌小孩閱讀 3,105評論 0 13
  • 今年春天诽嘉,業(yè)余時(shí)間我走入家庭指導(dǎo)父母如何教育孩子蔚出,這期間遇到了四五位被診斷為抑郁癥的青少年和長期抑郁的家長。后又聽...
    翟瑞婷閱讀 889評論 1 7