Android Retrofit 2.0 使用-补充篇

swkm4244 8年前
   <p>之前分享的 <a href="http://www.open-open.com/lib/view/open1465993338254.html">Android Retrofit 2.0 使用 </a>,属于基本的使用,实际开发还远远不够,因此对其补充,主要在Retrofit配置和接口参数。</p>    <h2>Retrofit配置</h2>    <h2>添加依赖</h2>    <p>app/build.gradle</p>    <pre>  <code class="language-java">compile 'com.squareup.retrofit2:retrofit:2.0.2'  </code></pre>    <p>首先Builder(),得到OkHttpClient.Builder对象builder</p>    <pre>  <code class="language-java">OkHttpClient.Builder builder = new OkHttpClient.Builder();  </code></pre>    <h2>Log信息拦截器</h2>    <p>Debug可以看到,网络请求,打印Log信息,发布的时候就不需要这些log</p>    <p>1、添加依赖</p>    <p>app/build.gradle</p>    <pre>  <code class="language-java">compile 'com.squareup.okhttp3:logging-interceptor:3.1.2'  </code></pre>    <p>2、Log信息拦截器</p>    <pre>  <code class="language-java">if (BuildConfig.DEBUG) {      // Log信息拦截器      HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();      loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);      //设置 Debug Log 模式      builder.addInterceptor(loggingInterceptor);  }  </code></pre>    <h2>缓存机制</h2>    <p>无网络时,也能显示数据</p>    <pre>  <code class="language-java">File cacheFile = new File(DemoApplication.getContext().getExternalCacheDir(), "WuXiaolongCache");  Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);  Interceptor cacheInterceptor = new Interceptor() {      @Override      public Response intercept(Chain chain) throws IOException {          Request request = chain.request();          if (!AppUtils.networkIsAvailable(DemoApplication.getContext())) {              request = request.newBuilder()                      .cacheControl(CacheControl.FORCE_CACHE)                      .build();          }          Response response = chain.proceed(request);          if (AppUtils.networkIsAvailable(DemoApplication.getContext())) {              int maxAge = 0;              // 有网络时 设置缓存超时时间0个小时              response.newBuilder()                      .header("Cache-Control", "public, max-age=" + maxAge)                      .removeHeader("WuXiaolong")// 清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清除下面无法生效                      .build();          } else {              // 无网络时,设置超时为4周              int maxStale = 60 * 60 * 24 * 28;              response.newBuilder()                      .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)                      .removeHeader("nyn")                      .build();          }          return response;      }  };  builder.cache(cache).addInterceptor(cacheInterceptor);  </code></pre>    <h2>公共参数</h2>    <p>可能接口有某些参数是公共的,不可能一个个接口都去加吧</p>    <pre>  <code class="language-java">//公共参数  Interceptor addQueryParameterInterceptor = new Interceptor() {      @Override      public Response intercept(Chain chain) throws IOException {          Request originalRequest = chain.request();          Request request;          String method = originalRequest.method();          Headers headers = originalRequest.headers();          HttpUrl modifiedUrl = originalRequest.url().newBuilder()                  // Provide your custom parameter here                  .addQueryParameter("platform", "android")                  .addQueryParameter("version", "1.0.0")                                .build();          request = originalRequest.newBuilder().url(modifiedUrl).build();          return chain.proceed(request);      }  };  //公共参数  builder.addInterceptor(addQueryParameterInterceptor);  </code></pre>    <h2>设置头</h2>    <p>有的接口可能对请求头要设置</p>    <pre>  <code class="language-java">Interceptor headerInterceptor = new Interceptor() {      @Override      public Response intercept(Chain chain) throws IOException {          Request originalRequest = chain.request();          Request.Builder requestBuilder = originalRequest.newBuilder()                  .header("AppType", "TPOS")                  .header("Content-Type", "application/json")                  .header("Accept", "application/json")                  .method(originalRequest.method(), originalRequest.body());          Request request = requestBuilder.build();          return chain.proceed(request);      }  };  //设置头  builder.addInterceptor(headerInterceptor );  </code></pre>    <h2>设置cookie</h2>    <p>服务端可能需要保持请求是同一个cookie,主要看各自需求</p>    <p>1、app/build.gradle</p>    <pre>  <code class="language-java">compile 'com.squareup.okhttp3:okhttp-urlconnection:3.2.0'  </code></pre>    <p>2、设置cookie</p>    <pre>  <code class="language-java">CookieManager cookieManager = new CookieManager();  cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);  builder.cookieJar(new JavaNetCookieJar(cookieManager));  </code></pre>    <h2>设置超时和重连</h2>    <p>希望超时时能重连</p>    <pre>  <code class="language-java">//设置超时  builder.connectTimeout(15, TimeUnit.SECONDS);  builder.readTimeout(20, TimeUnit.SECONDS);  builder.writeTimeout(20, TimeUnit.SECONDS);  //错误重连  builder.retryOnConnectionFailure(true);  </code></pre>    <p>最后将这些配置设置给retrofit:</p>    <pre>  <code class="language-java">OkHttpClient okHttpClient = builder.build();  Retrofit retrofit = new Retrofit.Builder()          .baseUrl(ApiStores.API_SERVER_URL)          //设置 Json 转换器          .addConverterFactory(GsonConverterFactory.create())          //RxJava 适配器          .addCallAdapterFactory(RxJavaCallAdapterFactory.create())          .client(okHttpClient)          .build();  </code></pre>    <h2>完整配置</h2>    <pre>  <code class="language-java">public class AppClient {      public static Retrofit retrofit = null;        public static Retrofit retrofit() {          if (retrofit == null) {            OkHttpClient.Builder builder = new OkHttpClient.Builder();              /**   *设置缓存,代码略   */                                      /**   * 公共参数,代码略   */                           /**   * 设置头,代码略   */                              /**   * Log信息拦截器,代码略   */                    /**   * 设置cookie,代码略   */                             /**   * 设置超时和重连,代码略   */                //以上设置结束,才能build(),不然设置白搭              OkHttpClient okHttpClient = builder.build();                retrofit = new Retrofit.Builder()                      .baseUrl(ApiStores.API_SERVER_URL)                                        .client(okHttpClient)                      .build();          }          return retrofit;        }  }  </code></pre>    <h2>接口参数</h2>    <h2>Path</h2>    <p>类似这样链接: <a href="/misc/goto?guid=4959674393697998561" rel="nofollow,noindex">http://wuxiaolong.me/2016/01/15/retrofit/</a></p>    <pre>  <code class="language-java">@GET("2016/01/15/{retrofit}")  Call<ResponseBody> getData(@Path("retrofit") String retrofit);  </code></pre>    <p>即您传的参数retrofit内容会替换大括号里的内容。</p>    <h2>Query</h2>    <p>类似这样链接: <a href="http://wuxiaolong.me/v1?ip=202.202.33.33&name=WuXiaolong" rel="nofollow,noindex">http://wuxiaolong.me/v1?ip=202.202.33.33&name=WuXiaolong</a></p>    <pre>  <code class="language-java">@GET("v1")  Call<ResponseBody> getData(@Query("ip") String ip,@Query("name") String name);  </code></pre>    <h2>Field</h2>    <p>表单提交,如登录</p>    <pre>  <code class="language-java">@FormUrlEncoded  @POST("v1/login")  Call<ResponseBody> userLogin(@Field("phone") String phone, @Field("password") String password);  </code></pre>    <h2>传json格式</h2>    <p>如果参数是json格式,如:</p>    <pre>  <code class="language-java">{        "apiInfo": {            "apiName": "WuXiaolong",            "apiKey": "666"        }    }  </code></pre>    <p>建立Bean</p>    <pre>  <code class="language-java">public class ApiInfo {         private ApiInfoBean apiInfo;           public ApiInfoBean getApiInfo() {             return apiInfo;         }           public void setApiInfo(ApiInfoBean apiInfo) {             this.apiInfo = apiInfo;         }           public class ApiInfoBean {             private String apiName;             private String apiKey;             //省略get和set方法         }     }  </code></pre>    <p>ApiStores</p>    <pre>  <code class="language-java">@POST("client/shipper/getCarType")  Call<ResponseBody> getData(@Body ApiInfo apiInfo);  ```           代码调用  ```java  ApiInfo apiInfo = new ApiInfo();  ApiInfo.ApiInfoBean apiInfoBean = apiInfo.new ApiInfoBean();  apiInfoBean.setApiKey("666");  apiInfoBean.setApiName("WuXiaolong");  apiInfo.setApiInfo(apiInfoBean);  //调接口  getData(apiInfo);  </code></pre>    <h2>传数组</h2>    <pre>  <code class="language-java">@GET("v1/enterprise/find")  Call<ResponseBody> getData(@Query("id") String id, @Query("linked[]") String... linked);  </code></pre>    <p>代码调用</p>    <pre>  <code class="language-java">String id="WuXiaolong";  String[] s = new String[]{"WuXiaolong"};  //调接口  getData(id, s);  </code></pre>    <h2>传文件-单个</h2>    <pre>  <code class="language-java">@Multipart  @POST("v1/create")  Call<ResponseBody> create(@Part("pictureName") RequestBody pictureName, @Part MultipartBody.Part picture);  </code></pre>    <p>代码调用</p>    <pre>  <code class="language-java">RequestBody pictureNameBody = RequestBody.create(MediaType.parse(AppConstants.CONTENT_TYPE_FILE), "pictureName");  File picture= new File(path);  RequestBody requestFile = RequestBody.create(MediaType.parse(AppConstants.CONTENT_TYPE_FILE), picture);  // MultipartBody.Part is used to send also the actual file name  MultipartBody.Part picturePart = MultipartBody.Part.createFormData("picture", picture.getName(), requestFile);  //调接口  create(pictureNameBody, picturePart);  </code></pre>    <h2>传文件-多个</h2>    <pre>  <code class="language-java">@Multipart  @POST("v1/create")  Call<ResponseBody> create(@Part("pictureName") RequestBody pictureName, @PartMap Map<String, RequestBody> params);  </code></pre>    <p>代码调用</p>    <pre>  <code class="language-java">RequestBody pictureNameBody = RequestBody.create(MediaType.parse(AppConstants.CONTENT_TYPE_FILE), "pictureName");  File picture= new File(path);  RequestBody requestFile = RequestBody.create(MediaType.parse(AppConstants.CONTENT_TYPE_FILE), picture);  Map<String, RequestBody> params = new HashMap<>();  params.put("picture\"; filename=\"" + picture.getName() + "", requestFile);  //调接口  create(pictureNameBody, params);  </code></pre>    <p>来自: <a href="/misc/goto?guid=4959674393864580954" rel="nofollow">http://wuxiaolong.me/2016/06/18/retrofits/</a></p>