Retrofit使用入门
- Retrofit底层基于okHttp,它更多的使用运行时注解的方式提供功能
- 相对于okhttp来说,retrofit相对来说做的主要是数据的处理封装
使用前先添加依赖
- 在项目的build.gradle下添加
dependencies {
compile 'com.squareup.retrofit2:retrofit:2.4.0'
}
- 关于他的具体版本可以去官方git查看
- 添加网络权限
开始使用前先看一下他的基本信息
注解类型
http请求方法注解
- GET ,POST , PUT , DELEFT , HEAD, PATCH , OPTIONS , HTTP
- 前七种分别对应http请求方法,而最后的HTTP则可以替换以上七种
标记类注解
- FormUrlEncodeed ,Multipart , Streaming
- 最后一个表示响应的数据会以流的形式返回,如果不使用它,默认会把全部数据加载到内存,所以当下载大文件时,需要加上这个注解
- 参数类注解
- Header , Headers, Body , Path , Field , FieldMap , Part , PartMap , Query , QueryMap
正式使用
简单使用(GET访问网络)
- 我们首先需要一个接口,这个接口提供了我们需要的返回数据的类型,先来看看最简单的使用,我们请求百度贴吧的官网(https://tieba.baidu.com/index.html?traceid=)
- 先写接口
public interface IpService{ @GET("index.html?traceid=") Call<ResponseBody> getIpMsg(); }
- 创建retrrofit实例
String url = "https://tieba.baidu.com/"; Retrofit retrofit = new Retrofit.Builder() .baseUrl(url) .build();
- 创建接口实例
IpService ipService = retrofit.create(IpService.class);
- 可以看到,我们的接口实例是由Retrofit为我们根据我们传入的class文件自行创建好的
- 接下来就是用接口实例得到访问网络的具体实例,以及访问网络
Call<ResponseBody> call = ipService.getIpMsg(); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { String s = null; try { s = response.body().string(); } catch (IOException e) { e.printStackTrace(); } Log.d(TAG, "onResponse: "+s); } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { } });
- 可以看到,最后是通过我们的接口去得到的访问网络的实例,最后再去访问网络,不难理解,这里的log打出的就是得到的贴吧官网的html文件
- 因为我们是直接拿ResponseBody所以直接就写的是ResponseBody。
- 上面我们说过,retrofit主要做的是对数据类的封装,可是这里并没有看出有什么效果,下面就来看一下他的用法
实现对数据的封装
- 上面说我们要对数据封装,那么刚才ResponseBody的地方就不能再写ResponseBody了,而是换成我们自己需要得到的数据类型
- 其他地方都是一样,这里我就直接放代码,我在这里请求的是一个公开的获取网名api接口(https://www.apiopen.top/femaleNameApi?page=1)
public void requestNetByRetrofitTest02(){ String url = "https://www.apiopen.top/"; Retrofit retrofit = new Retrofit.Builder() .baseUrl(url) .addConverterFactory(GsonConverterFactory.create()) .build(); IpServiceTest02 ipServiceTest02 = retrofit.create(IpServiceTest02.class); Call<NetNameApiDate> call = ipServiceTest02.getcall(); call.enqueue(new Callback<NetNameApiDate>() { @Override public void onResponse(Call<NetNameApiDate> call, Response<NetNameApiDate> response) { NetNameApiDate.Name[] dates = response.body().data; for (int i = 0;i < dates.length ; i++){ Log.d(TAG, "onResponse: "+dates[i].femalename); } } @Override public void onFailure(Call<NetNameApiDate> call, Throwable t) { } }); } public interface IpServiceTest02{ @GET("femaleNameApi?page=1") Call<NetNameApiDate> getcall(); }
- 再来看一下我们自己写的这个数据类
public class NetNameApiDate { int code = -1; String msg = null; Name[] data; class Name{ public String femalename; } }
- 这里这个类的写法是根据Json数据格式解析写的,不懂的同学可以去看一下Json数据解析的方法
以上两种就是最基本的体现retrofit功能的写法,接下来我们看看他都有什么好的用法
1.动态配置path地址:@path
- 比如我们的接口中可以这么写
public interface IpServiceTest03{ @GET("{path}?page=1") Call<NetNameApiDate> getcall(@Path("path") String path); }
- 那么,再去得到网络访问实例的时候就应该
Call<NetNameApiDate> call = ipServiceTest03.getcall("femaleNameApi");
- 可以理解,这个字符串参数就会被拿进去放到path的位置,其他都一样的,不再说明
2.动态指定条件:@Query
- 我们可以看到在这个接口的末尾是对指定page的查询,那么我们就可以动态的指定这个page
public interface IpServiceTest03{ @GET("{path}") Call<NetNameApiDate> getcall(@Path("path") String path, @Query("page") String page); }
- 同样在获取Call实例的时候
Call<NetNameApiDate> call = ipServiceTest03.getcall("femaleNameApi","1");
- 不需要讲解
3.有时候查询条件不止一个甚至更多,这时候再用一个个Query的话未免太麻烦,于是,Retrofit为我们提供了动态查询组:@QueryMap
- 这里就不再说明,只不过把所有的查询条件放到一个Map里面就好
POST访问网络
1.传输数据类型为键值对:@Field
- 依然是改接口
public interface IpServiceTest04{ @FormUrlEncoded @POST("femaleNameApi") Call<NetNameApiDate> getcall(@Field("page") String page); }
- 这里的第一行注解代表我们这个是表单请求
- 网络请求方式变成了POST,同时在参数列表里放上我们的表单列表
- 其他都一样的,不再说明
2.传输数据类型为字符串:@Body
- 当我们想要上传某个东西时,会用到,依旧改接口
public interface IpServiceTest05{ @POST("femaleNameApi") Call<NetNameApiDate> getcall(@Body MyData da); } class MyData{ String i; public MyData(String i){ this.i = i; } }
- 声明我们要传递的对象,然后将对象实例传进去,然后Retrofit会自动将我们的对象转换成字符串
3.单个文件上传
- 继续改接口
public interface IpServiceTest06{ @Multipart @POST("这里写请求网址") Call<MyData> updataMyData(@Part MultipartBody.Part data, @Part("description")RequestBody description); }
- 这里的参数是通过MultipartBody.Part和RequestBody 创建出来的,具体用法还是用的时候再说吧,这里也不太好实践
4.多个文件上传
- 接口
public interface IpServiceTest07{ @Multipart @POST("这里写请求网址") Call<MyData> updataMyData(@PartMap Map<String,MultipartBody.Part> datas, @Part("description")RequestBody description); }
消息报头Header
- 静态方式
public interface IpServiceTest08{ @GET("这里写请求网址") @Headers("Accept-Encoding:application/json") Call<RequestBody> getCarType(); }
- 如果多个请求头
public interface IpServiceTest08{ @GET("这里写请求网址") @Headers({ "Accept-Encoding:application/json", "User-Agent:MoonRetrofit" }) Call<RequestBody> getCarType(); }
- 动态方式
public interface IpServiceTest09{ @GET("这里写请求网址") Call<RequestBody> getCarType( @Header("Accept-Encoding") String s ); }