retrofit学习

前言

Retrofit是一个网络请求,用法简洁方便,一起来学习一下吧O(∩_∩)O~

一、配置

工具是 Android Studio,所以这里只讲AndroidStudio的配置
**1. build.gradle **
首先,如图添加retrofit和okhttp


retrofit学习_第1张图片
Paste_Image.png
    compile 'com.squareup.retrofit2:retrofit:2.2.0'
    compile 'com.squareup.okhttp3:okhttp:3.6.0'

2. 添加网络权限

    

二、静态参数接口GET请求

接口用http://gank.io/api/data/Android/10/1这个

retrofit学习_第2张图片

然后,我们就开始获取数据啦~
1. 定义一个接口类
这个接口我们用https:// ..com/goods/tags/goods/1?g_id=0

  public interface Api {
    @GET("goods/tags/goods/1?g_id=0")
    Call getData(); //retrofit下的call
}

2. 开始请求
接口需要大家自己找一个写啦O(∩_∩)O~
1. 返回ResponseBody

Retrofit retrofit = new Retrofit.Builder().baseUrl(Api.baseUrl).build();
      Api api = retrofit.create(Api.class);
      Call call = api.getData();
      //开始异步请求
      call.enqueue(new Callback() {
          @Override
          public void onResponse(Call call, Response response) {
              try {
                  String data = response.body().string();
                  txt.setText(data);
              }
              catch (IOException e) {
                  e.printStackTrace();
              }
          }

          @Override
          public void onFailure(Call call, Throwable t) {
              t.printStackTrace();
          }
      });
retrofit学习_第3张图片
结果

2. 返回解析后的对象
注意注意:必须创建一个转换器,才可以哦,不然会发现 Unable to create converter for ...的错误哦

  1. 添加转换器


    retrofit学习_第4张图片
    compile 'com.squareup.retrofit2:converter-gson:2.2.0'
  2. 根据gson解析工具建立实体类,不建议使用,原因后面说~
public class ResultBean {
...
 private int id;
...
}

3.开始使用
把responseBody改成ResultBean,然后加上converter转换器就好

  @GET("goods/tags/goods/1?g_id=0")
    Call getObjectBean();
   Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .build();

 Api api = retrofit.create(Api.class);//接口对象
 Call call = api.getObjectBean();
        //开始异步请求
        call.enqueue(new Callback() {
            @Override
            public void onResponse(Call call, Response response) {
                    ResultBean resultBean = response.body();
                    txt.setText(resultBean.getData().toString());
            }

            @Override
            public void onFailure(Call call, Throwable t) {
                t.printStackTrace();
            }
   });

有没有人出错的?

retrofit学习_第5张图片

尴尬了,为什么呢?因为gson解析错误,主要是因为服务器返回的数据应该是array:[],但是返回成了这样子的array:null,所以说,为了防止这种问题,就 最好是使用responseBody,然后自己解析

三、动态参数接口GET请求

  1. 接口的最终样式是goods/tags/goods/1?g_id=0,这里我们将g_id的值动态改变
  @GET("goods/tags/goods/1")
    Call getGoodsData(@Query("g_id") int id);
...
        Call call = api.getGoodsData(0);
...
  1. 将1?g_id=0都动态改变
    @GET("goods/tags/goods/{page}")
    Call getGoodsDataInfo(@Path("page") int page, @Query("g_id") int id);
   Call call = api.getGoodsDataInfo(1,0);
  1. 动态添加不确定数量的参数和类型
   @GET("goods/tags/goods/{page}")
    Call getGoodsDataParams(@Path("page") int page,@QueryMap Map params);
        HashMap hash = new HashMap<>();
        hash.put("page",1);
        hash.put("g_id", 0);
        Call call = api.getGoodsDataParams(1, hash);
  1. 传数组
@GET("v1/enterprise/find")
Call getData(@Query("id") String id, @Query("linked[]") String... linked);

四、Post请求

由于没有接口,只能这样子啦

  1. Post表单提交
 @FormUrlEncoded
@POST("user/edit")
Call editUser(@Field("id") int id, @Field("name") String name);

如果报了@Field parameters can only be used with form encoding这个错误,则需要使用 @FormUrlEncoded

api.editUser(1, "liuguilin").enqueue(new Callback() {
     @Override
     public void onResponse(Call call, Response response) {
         if (response.body().getYes() == 0) {
             Toast.makeText(MainActivity.this, "成功", Toast.LENGTH_SHORT).show();
         }
     }

     @Override
     public void onFailure(Call call, Throwable t) {

     }
 });
  1. Post传json格式
{
 data:""
}
public class DataBean {
    private String data;
      ...
}
@POST("user/data")
Call getData(@Body DataBean data);
  1. Post传文件-单个
@Multipart
@POST("file/create")
Call create(@Part("pictureName") RequestBody pictureName,  @Part MultipartBody.Part picture);
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);
  1. Post传文件-多个
@Multipart
@POST("files/create")
Call create(@Part("pictureName") RequestBody pictureName,   @PartMap Map params);
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 params = new HashMap<>();
params.put("picture\"; filename=\"" + picture.getName() + "", requestFile);
//调接口
create(pictureNameBody, params);

五、添加Header

@Headers("Cache-Control: max-age=640000")
@GET("widget/list")
Call> widgetList();

六、log信息拦截

 compile 'com.squareup.okhttp3:logging-interceptor:3.6.0'
    OkHttpClient.Builder builder = new OkHttpClient.Builder();
   if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
           httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(httpLoggingInterceptor);
 }

七、完整配置

 OkHttpClient.Builder builder = new OkHttpClient.Builder();
        if (BuildConfig.DEBUG) {
            HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
            httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
            builder.addInterceptor(httpLoggingInterceptor);
        }
        initCache(builder);
        initParameter(builder);
        initTimeOut(builder);
        //将这些配置设置给retrofit
        OkHttpClient client = builder.build();

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)
                .addConverterFactory(GsonConverterFactory.create())
                .client(client)
                .build();


        Api api = retrofit.create(Api.class);//创建接口对象
  //设置超时和重连
    private void initTimeOut(OkHttpClient.Builder builder) {
        //设置超时
        builder.connectTimeout(15, TimeUnit.SECONDS);
        builder.readTimeout(20, TimeUnit.SECONDS);
        builder.writeTimeout(20, TimeUnit.SECONDS);
        //错误重连
        builder.retryOnConnectionFailure(true);
    }

    //添加公共参数
    private void initParameter(OkHttpClient.Builder builder) {
        Interceptor parameterInterceptor = new Interceptor() {
            @Override
            public okhttp3.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()
                        .addQueryParameter("platform", "android")
                        .addQueryParameter("version", "1.0.0")
                        .build();
                request = originalRequest.newBuilder().url(modifiedUrl).build();
                return chain.proceed(request);
            }
        };
        builder.addInterceptor(parameterInterceptor);
    }


    //设置缓存,无网络时,也能显示数据
    private void initCache(OkHttpClient.Builder builder) {
        File cacheFile = new File(this.getExternalCacheDir(), "cache");
        Cache cache = new Cache(cacheFile, 1024 * 1024 * 50);//缓存文件50M
        Interceptor interceptor = new Interceptor() {

            @Override
            public okhttp3.Response intercept(Chain chain) throws IOException {
                Request request = chain.request();
                if (!netWorkIsAvailable) {//网络不可用
                    request = request.newBuilder().cacheControl(CacheControl.FORCE_CACHE).build();
                }
                else {//网络可用
                    request = request.newBuilder()
                            .cacheControl(CacheControl.FORCE_NETWORK)
                            .build();
                }
                okhttp3.Response response = chain.proceed(request);
                if (netWorkIsAvailable) {
                    int maxAge = 0;
                    response.newBuilder()
                            .header("Cache-Control", "public, max-age=" + maxAge)//覆盖服务器响应头的Cache-Control,用我们自己的,因为服务器响应回来的可能不支持缓存
                            .removeHeader("Pragma")//清除头信息,因为服务器如果不支持,会返回一些干扰信息,不清无法生效
                            .build();
                }
                else {
                    int maxStale = 60 * 60 * 24 * 28;//无网络时,设置超时为4周
                    response.newBuilder()
                            .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                            .removeHeader("Pragma")
                            .build();
                }
                return response;
            }
        };
        builder.cache(cache).addInterceptor(interceptor);
    }

八、移除请求

call.cancel();

后记

Github:https://github.com/square/retrofit
官网文档:http://square.github.io/retrofit/

参考网址

Retrofit2.0通俗易懂的学习姿势,Retrofit2.0 + OkHttp3 + Gson + RxJava
Android Retrofit 2.0 使用-补充篇
Retrofit中如何正确的使用https?

你可能感兴趣的:(retrofit学习)