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>