本文主要是参考慕课网Jennynick老师视频所做出的总结。
一、首先明白一点:
Retrofit是基于Okhttp网络框架进行的二次封装,其本质仍是Okhttp。(类似乌尔奇奥拉的二段归刃)
另外,科普一下,Android5.0之后不再使用HttpClient了。本来还想着看看httpclient的高阶用法呢,你看,多学习就可以少学习。
二、同Volley对比:
Volley基于HttpUrlConnction,Google官方推出,只适用于轻量级网络交互,不适合大文件下载上传场景。
没有对比就没有伤害,伤害了Volley突出了Retrofit如下优点:
API设计简洁易用、注解化配置高度解耦、支持多种解析器、支持Rxjava
实际操作:
一、依赖包导入
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
implementation 'com.squareup.retrofit2:converter-gson:2.0.2'
网络权限别忘了申请~
二、创建接口设置请求类型与参数
ex:新建UserInfoModel类和UserMgrService接口:
@GET("login")
public Call<UserInfoModel> login(@Query("username") String username,@Query("pwd") String pwd);
(login是UserMgrService里的一个方法)
三、创建Retrofit对象、设置数据解析器
Retrofit retrofit=new Retrofit.Builder().baseUrl(Constants.BASE_URL).addConverterFactory(GsonConverterFactory.create())).build();
数据解析器支持类型有:
Gson、Jackson、Simple XML、 Protobuf、Moshi、Wire、Scalars
四、生成接口对象
UserMgrService service=retrofit.create(UserMgrService.class);
五、调用接口方法返回Call对象
Call call=service.login(“zhangsan”,“2345”);
六、发送请求(同步、异步)
同步:调用Call对象的execute(),返回结果的响应体(如果是耗时操作,可能导致ANR,需要处理)
异步:调用Call对象的enqueue(),参数是一个回调
请求方法有如下几个:
@GET 表示这个一个get请求
@POST 表示这是一个post请求
@PUT …
@DELETE …
@HEAD …
@OPTIONS …
@PATCH …
请求参数如下:
@Headers 添加请求头
@Path 替换路径
@Query 替代参数值,通常是结合get请求的
@FormUrlEncoded 用表单数据提交
@Field 替换参数值,是结合post请求的
@Body 可以用来提交 Json 数据或者上传文件
@QueryMap:包含多个@Query注解参数(传递较多参数时使用)
GET请求
七、请求实例:
① 新建一个接口,声明请求方法
② 在activity中声明retrofit,并调用接口里的方法。
测试调用github的api:(以下Demo均是在此Url基础上拼接)
https://api.github.com/
无参:(最简单的get请求)
@GET("/")//不传参数
Call<ResponseBody> getMessages();
@Path替换路径:(URL中有参数)
@GET("repos/{owner}/{repo}")//路径为:https://api.github.com/repos/{owner}/{repo}
Call<ResponseBody> getMessages3(@Path("owner") String owner,@Path("repo") String repo);//替换路径
@Path和@Query一块使用:(URL中有参数且URL问号之后有参数)
@GET("users/{user}/repos")//路径:https://api.github.com/users/{user}/repos{?type,page,per_page,sort}
Call<ResponseBody> getMessages4(@Path("user") String user,
@Query("page") int page,@Query("per_page")int per_page);
@QueryMap的使用(URL中问号之后有多个参数且个数不固定)
@GET("users/{user}/repos")
Call<ResponseBody> getMessages5(@Path("user") String user, @QueryMap HashMap<String,Integer> info);
_________________________________
HashMap<String,Integer> params=new HashMap<>();
params.put("page",1);
params.put("per_page",3);
Call<ResponseBody> call=api.getMessages5("SprrowZ",params);
好,今天先更到这里。
继续来个实例:
public interface GithubApi {
/**
* GET请求
* @return
*/
//访问文件地址:https://raw.githubusercontent.com/SprrowZ(用户名)/AndroidZex(仓库名)/master(分支)/.gitignore(路径)
@GET("/")//不传参数
Call<ResponseBody> getMessages();
@GET("users/SprrowZ")//这个参数是用来拼路径的,https://api.github.com/users/{user},就是这里的{user}
Call<ResponseBody> getMessages2();
@GET("repos/{owner}/{repo}")//路径为:https://api.github.com/repos/{owner}/{repo},{owner}/{repo}
Call<ResponseBody> getMessages3(@Path("owner") String owner,@Path("repo") String repo);//替换路径
@GET("users/{user}/repos")//路径:https://api.github.com/users/{user}/repos{?type,page,per_page,sort}
Call<ResponseBody> getMessages4(@Path("user") String user,
@Query("page") int page,@Query("per_page")int per_page);
@GET("users/{user}/repos")
Call<ResponseBody> getMessages5(@Path("user") String user, @QueryMap HashMap<String,Integer> info);
}
private void retrofitGet1() {
new Thread(()->{
Retrofit retrofit=new Retrofit.Builder()
.baseUrl(Constant.GITHUB_BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
GithubApi service=retrofit.create(GithubApi.class);
Call<ResponseBody> call=service.getMessages();
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
System.out.println(response.body().toString());
try {
content1.setText("get无参:"+"\n"+response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
t.printStackTrace();
}
});
}).start();
}
重点讲一下这个:.addConverterFactory(GsonConverterFactory.create())
Converter就是Retrofit为我们提供用于将ResponseBody转换为我们想要的类型,看最上面我们接受返回类型的时候不是ResponseBody而是UserInfoModel,这个类是我们建的实体类,用来接受返回的数据,当数据不复杂时用这个更方便操作,如果复杂的话直接用ResponseBody比较好,个人感觉。。
FBI WARNING
response.body().string()
只有第一次有取到值!!!!所以务必赋值给一个String ,然后操作这个对象!
如果不信的话,可以打两个log,都输出response.body().string()
你就会发现第二次没有值,这个是正常的,看源码就晓得了,节省资源的策略。
POST请求
Post请求需要把请求参数放置在请求体中,而非拼接在url后面,先介绍两个注解:
@FormUrlEncoded将会自动将请求参数的类型调整为application/x-www-form-urlencoded,需要注意的是:FormUrlEncoded不能用于Get请求。这个注解主要是和@Field配合使用的,@Field注解将每一个请求参数都存放至请求体中,还可以添加encoded参数,该参数为boolean;@FormUrlEncoded 与 @FieldMap注解结合表示以表单的方式传递键值对