本文主要應用了OkHttp的Interceptor來實現自定義重試次數 雖然OkHttp自帶retryOnConnectionFailure(true)方法可以實現重試,但是不支持自定義重試次數,所以有時並不能滿足我們的需求。 #1.自定義重試攔截器: #2.測試場景類: #3.輸出結果: #4.結 ...
本文主要應用了OkHttp的Interceptor來實現自定義重試次數
雖然OkHttp自帶retryOnConnectionFailure(true)方法可以實現重試,但是不支持自定義重試次數,所以有時並不能滿足我們的需求。
#1.自定義重試攔截器:
/** * 重試攔截器 */ public class RetryIntercepter implements Interceptor { public int maxRetry;//最大重試次數 private int retryNum = 0;//假如設置為3次重試的話,則最大可能請求4次(預設1次+3次重試) public RetryIntercepter(int maxRetry) { this.maxRetry = maxRetry; } @Override public Response intercept(Chain chain) throws IOException { Request request = chain.request(); System.out.println("retryNum=" + retryNum); Response response = chain.proceed(request); while (!response.isSuccessful() && retryNum < maxRetry) { retryNum++; System.out.println("retryNum=" + retryNum); response = chain.proceed(request); } return response; } }
#2.測試場景類:
1 public class RetryTest { 2 String mUrl = "https://www.baidu.com/"; 3 OkHttpClient mClient; 4 5 @Before 6 public void setUp() { 7 HttpLoggingInterceptor logging = new HttpLoggingInterceptor(); 8 logging.setLevel(HttpLoggingInterceptor.Level.BODY); 9 10 mClient = new OkHttpClient.Builder() 11 .addInterceptor(new RetryIntercepter(3))//重試 12 .addInterceptor(logging)//網路日誌 13 .addInterceptor(new TestInterceptor())//模擬網路請求 14 .build(); 15 } 16 17 @Test 18 public void testRequest() throws IOException { 19 Request request = new Request.Builder() 20 .url(mUrl) 21 .build(); 22 Response response = mClient.newCall(request).execute(); 23 System.out.println("onResponse:" + response.body().string()); 24 } 25 26 class TestInterceptor implements Interceptor { 27 28 @Override 29 public Response intercept(Chain chain) throws IOException { 30 Request request = chain.request(); 31 String url = request.url().toString(); 32 System.out.println("url=" + url); 33 Response response = null; 34 if (url.equals(mUrl)) { 35 String responseString = "{\"message\":\"我是模擬的數據\"}";//模擬的錯誤的返回值 36 response = new Response.Builder() 37 .code(400) 38 .request(request) 39 .protocol(Protocol.HTTP_1_0) 40 .body(ResponseBody.create(MediaType.parse("application/json"), responseString.getBytes())) 41 .addHeader("content-type", "application/json") 42 .build(); 43 } else { 44 response = chain.proceed(request); 45 } 46 return response; 47 } 48 } 49 50 }
#3.輸出結果:
1 retryNum=0 2 --> GET https://www.baidu.com/ HTTP/1.1 3 --> END GET 4 url=https://www.baidu.com/ 5 <-- 400 null https://www.baidu.com/ (13ms) 6 content-type: application/json 7 8 {"message":"我是模擬的數據"} 9 <-- END HTTP (35-byte body) 10 retryNum=1 11 --> GET https://www.baidu.com/ HTTP/1.1 12 --> END GET 13 url=https://www.baidu.com/ 14 <-- 400 null https://www.baidu.com/ (0ms) 15 content-type: application/json 16 17 {"message":"我是模擬的數據"} 18 <-- END HTTP (35-byte body) 19 retryNum=2 20 --> GET https://www.baidu.com/ HTTP/1.1 21 --> END GET 22 url=https://www.baidu.com/ 23 <-- 400 null https://www.baidu.com/ (0ms) 24 content-type: application/json 25 26 {"message":"我是模擬的數據"} 27 <-- END HTTP (35-byte body) 28 retryNum=3 29 --> GET https://www.baidu.com/ HTTP/1.1 30 --> END GET 31 url=https://www.baidu.com/ 32 <-- 400 null https://www.baidu.com/ (0ms) 33 content-type: application/json 34 35 {"message":"我是模擬的數據"} 36 <-- END HTTP (35-byte body) 37 onResponse:{"message":"我是模擬的數據"}
#4.結果分析:
>1. 這裡我用一個TestInterceptor攔截器攔截掉真實的網路請求,實現response.code的自定義
2. 在RetryIntercepter中,通過response.isSuccessful()來對響應碼進行判斷,迴圈調用了多次chain.proceed(request)來實現重試攔截
3. 從輸出中可以看到,一共請求了4次(預設1次+重試3次)。
#5.其它實現方式
如果你是使用OkHttp+Retrofit+RxJava,你也可以使用retryWhen操作符:retryWhen(new RetryWithDelay())來實現重試機制
1 public class RetryWithDelay implements Func1<Observable<? extends Throwable>, Observable<?>> { 2 3 private final int maxRetries; 4 private final int retryDelayMillis; 5 private int retryCount; 6 7 public RetryWithDelay(int maxRetries, int retryDelayMillis) { 8 this.maxRetries = maxRetries; 9 this.retryDelayMillis = retryDelayMillis; 10 } 11 12 @Override 13 public Observable<?> call(Observable<? extends Throwable> attempts) { 14 return attempts 15 .flatMap(new Func1<Throwable, Observable<?>>() { 16 @Override 17 public Observable<?> call(Throwable throwable) { 18 if (++retryCount <= maxRetries) { 19 // When this Observable calls onNext, the original Observable will be retried (i.e. re-subscribed). 20 LogUtil.print("get error, it will try after " + retryDelayMillis + " millisecond, retry count " + retryCount); 21 return Observable.timer(retryDelayMillis, 22 TimeUnit.MILLISECONDS); 23 } 24 // Max retries hit. Just pass the error along. 25 return Observable.error(throwable); 26 } 27 }); 28 } 29 }