老生常谈
- 什么是 Retrofit ?
- Retrofit 早已不是什么新技术了,想必看到这篇博客的大家都早已熟知,这里就不啰嗦了,简单介绍下:
- Retrofit 是一个针对 Java 和 Android 的设计的 REST 客户机。它通过基于 REST 的 web 服务检索和上传 JSON (或其他结构化数据)变得相对容易。在使用中,您可以配置用于数据序列化的转换器。对于 JSON ,通常使用Gson ,但是可以添加自定义转换器来处理 XML 或其他协议。Retrofit 对 HTTP 请求使用 OkHttp 库。
A type-safe HTTP client for Android and Java
- 好了介绍结束,想必大家的大刀都饥渴难耐了,那么我们直接开始吧
本文流程
依赖注入
- so Easy 不用说了吧
- 在 app module 下的 build.gradle 中添加以下依赖:
// OkHttp3
api 'com.squareup.okhttp3:okhttp:3.10.0'
api 'com.squareup.okio:okio:1.8.0'
// Retrofit
api 'com.squareup.retrofit2:retrofit:2.7.0'
// Gson 服务器数据交互
api 'com.google.code.gson:gson:2.8.6'
依赖注入很简单, Retrofit 一直是结合 OkHttp 和 Gson(无所谓什么 JSON 解析器都行,这里就用 Gson 了) 我这里专门找了最新的版本库,so~ 大家直接用即可
- 别急,前面也说了 Retrofit 是结合 OkHttp 做网络请求用的,所以悉心提醒记得开下网络权限:
<uses-permission android:name="android.permission.INTERNET" />
全面进击
- 网上关于 Retrofit 的教程可谓琳瑯满目,但是总给人一种云里雾里的感觉
- 所以本文的亮点就在于,我会通过我自己实际项目的代码来给大家介绍 Retrofit 到底牛在哪
Retrofit 开始之前
- 这里我将以一个开源项目 FIWKeepApp 的登录模块举例
- 在 Retrofit 出现之前,原始社会的我们一般是这样进行网络请求的:
public void login2() {
OkHttpClient okHttpClient = new OkHttpClient();
//Form表单格式的参数传递
FormBody formBody = new FormBody
.Builder()
//设置参数名称和参数值
.add("username",mAccountEdit.getText().toString())
.add("password",mPasswordEdit.getText().toString())
.build();
Request request = new Request
.Builder()
//Post请求的参数传递
.post(formBody)
.url("http://hyh.hljdx.net:8080/SitUpWebServer/login")
.build();
okHttpClient.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(okhttp3.Call call, IOException e) {
Log.d("my_Test", e.getMessage());
}
@Override
public void onResponse(okhttp3.Call call, Response response) throws IOException {
String result = response.body().toString();
UserBean userBean = JSON.parseObject(result, UserBean.class);
Log.d("my_Test",userBean.getUser_head_img());
response.body().close();
}
});
}
- 有没有一种云里雾里的感觉?
- 首先你得先将要发送的表单信息封装为 Post 请求的 Body 对象,那么有的同学会问什么是 POST ,什么是 Body?这个问题建议大家 Google 下,这里我建议大家学一些后端或者计网的知识,很简单也很有必要
- 接着你需要再封装一个 Request 对象,也就是我们的请求体,在这里设置信息要提交到哪去
- 最后调用 okHttpClient 的相应方法,将前面实现的东西组合发送,并在回调里接收
- 所以,这一步步,又是封装 FormBody 又是封装 Request ,搞了半天还要用 okHttpClient 发送,一套下来头晕眼花,那么如何解决呢?
- 那么 Retrofit 救世主就出现了
Retrofit 实现
- 还是项目中的登录模块,我将其改为 Retrofit 的形式
- 同样完成上面的功能,如果用 Retrofit 实现只需要:
// baseUrl() 设置路由地址
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl(ApiUtils.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
// 设置参数
Call<UserBean> call = retrofit.create(UserMgrService.class)
.login( mAccountEdit.getText().toString(),
mPasswordEdit.getText().toString());
// 回调
call.enqueue(new Callback<UserBean>() {
@Override
public void onResponse(Call<UserBean> call, Response<UserBean> response) {
Log.d("123123", "msg--" + response.body().getUser_head_img());
}
@Override
public void onFailure(Call<UserBean> call, Throwable t) {
// 失败时做处理
}
});
- 如上就实现了和纯 okHttp 代码一样的功能
- 大家可能会觉得,这也没简单多少啊 ?但细心观察发现,第一步 Retrofit 的实例化过程,只要服务器不换代码几乎是不变的,所以我们完全可以将它封装
- 而且大家有没有发现,如果单单使用 OkHttp 我们的返回值是一个 Response 对象,我们还需要在其中提取相应 JSON 对象,进行类型转换,而在 Retrofit 中,由于使用了数据解析器,所以这一大块代码都省略了
- 还有很多优点,这里就不唠叨了,我们直接开始学习使用之路吧!
实现流程
- 那么现在就给大家解释下使用的每个步骤
创建接口
- 首先我们要创建 UserMgrService 接口
/**
* @author fishinwater-1999
* @version 2019-12-21
*/
public interface UserMgrService {
/**
* GET 用 Query
*/
@GET("login")
Call<UserBean> login(@Query("username") String username, @Query("password") String password);
}
- 从 @GET() 注解就可以猜到,这将会是一个 Get 请求
- 我们在看方法体,返回值会是一个封装了 UserBean 的 Call<> 对象
- 参数有两个,分别是 String username 和 String password
- 与平常方法不同的是,这两个参数各自带上了 @Query("...") 注解
- 通过 @Query("...") 里的参数我们发现,这与 okHttp 创建 FormBody 时,add 的参数不谋而合
看到这里想必大家都明白了,如果大家还不明白什么是 Get 请求,以及 @Query("...") 里的 username 和 password 是怎么的话,我这里简单说下 比如说我们现在随便打开一个网页,就拿百度图片里搜索 Github 页面为例:
- 后端写服务器的同学会通过这些参数,像 HashMap get(“key”) 方法取值一样拿出来
- POST
- 这样解释,想必大家就明白了
- 除了 GET 方法之外 还有一种 POST 方法,相比于使用 GET ,使用 POST 有很多其他的优点,这里就不多说了
- 他使用和 GET 的思路一样,如果用 POST 那么我们的代码将会是这样的:
public interface UserMgrService {
/**
* POST 用 Field
*/
@POST("login")
@FormUrlEncoded
Call<UserBean> login(@Field("username") String username, @Field("password") String password);
}
- 就是把注解换了套名字,然后在 @POST("...") 下再加上一个 @FormUrlEncoded 注解
- 这里就不多说了,我们直接进入下一步
生成 Retrofit 对象
- 我们先看下怎么创建和设置的:
// baseUrl() 设置路由地址
Retrofit retrofit = new Retrofit
.Builder()
.baseUrl(ApiUtils.BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
- 这里主要是两步,设置 baseUrl 、设置数据解析器
- 老样子什么是 baseUrl ?就拿我之前用 OkHttp 设置的那个 url 为例
http://hyh.hljdx.net:8080/SitUpWebServer/login
- 大家可以这么理解:上面的这个 url = baseurl + @GET("...") 注解里传入的字符串
- 如果我们前面设置的是 @GET("login") 那这里 baseurl 就是:http://hyh.hljdx.net:8080/SitUpWebServer/ 是不是一下子就明白了,但是其他博客不照顾新人,从没说清楚
- 然后就是数据解析器,大家应该还记得刚开始的时候我们导入了一个三方库:
// Gson 服务器数据交互
api 'com.google.code.gson:gson:2.8.6'
- 我们和服务器的数据,都是以 JSON 的形式交互的,比如 Bing 每日壁纸接口
- 设置了这个数据解析器,就可以把返回的信息自动封装为相应的对象,明白了吧
具体这个对象怎么获得,大家可以联系后端,或者百度搜下 JsonFormat 插件使用或者 JSON 对象生成器,门路很多这里都告诉你们啦
生成接口对象
- 老样子,先看看代码
UserMgrService service = retrofit.create(UserMgrService.class);
- 过于简单,调用前面 retrofit 对象的 create() 方法传入接口的 class 文件即可
获得 Call 对象
- 由刚开始的代码我们知道
- 我们向服务器发送请求需要调用 call 对象的 enqueue() 方法
- 那么 Call 对象怎么获得呢?其实很简单:
Call<UserBean> call = service.login( mAccountEdit.getText().toString(), mPasswordEdit.getText().toString());
- 说白了就是,直接调用接口的相应方法,他返回的直接就是一个 Call 对象
发送请求
- 请求分两种 同步的和异步的
- 由于请求是耗时的,假设我们发送同步请求 ,在请求就过返回之前,应用界面会进去阻塞状态
- 说白了就是会卡,甚至卡死。。。所以说这种请求很少用到
- 虽然不用,但负责的我还是也给大家代码:
Response<UserBean> response = call.execute();
Log.d("123123", "msg--" + response.body().getUser_head_img());
- 具体就不说了,就是调用 call 的 execute() 会返回一个值
- 这个值就是请求结果,大家直接用就是( 但是在这个只没返回,比如网速慢时,手机会卡在那动不了甚至 ANR )
- 这里我介绍下异步请求:
// 回调
call.enqueue(new Callback<UserBean>() {
@Override
public void onResponse(Call<UserBean> call, Response<UserBean> response) {
Log.d("123123", "msg--" + response.body().getUser_head_img());
}
@Override
public void onFailure(Call<UserBean> call, Throwable t) {
// 失败时做处理
}
});
- 这就是异步方法,直接调用 call 的 enqueue 方法,传入一个 Callback 接口即可
- 调用后系统自动释放资源,不会阻塞,等到请求结果返回时
- 就会自动调用 onResponse 方法,方法 里的 response 就是处理好的结果
- 本文代码运行后结果 Demo Example 是不是特别简单!
更多模块实战 FIWKeepApp
- 这里我将上述过程写在我的 Demo 里,地址在 GitHub 大家可以直接查看改仓库源码,记得给我点个 star 哦~:
- Demo 地址:https://github.com/FishInWater-1999/FIWKeepApp/blob/master/usercenter/src/main/java/com/fishinwater/login/ui/fragment/LoginFragment.java
总结
- 想必看到这儿的读者对 Retrofit 的使用都已近有了一定的了解,但 Retrofit 的好处并不只是这些,还有很多跟深入的只是需要了解,但本文限于篇幅,无法向大家一一介绍
- 对于前面的 FIWKeepApp 这个仓库,我将一步步转换到 Retrofit + OkHttp 的形式下,欢迎大家关注我的 这个仓库,进行学习,也欢迎各位老铁给个 star
- 后面我还会对 Android 的各种知识点、Framework 层源码,三方库等进行解析,欢迎大家关注,及时接收更多优质博文!
感谢大家能耐着性子看完啰里啰嗦的文章
在这里我也分享一份私货,自己收录整理的Android学习PDF+架构视频+面试文档+源码笔记,还有高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料帮助大家学习提升进阶,也节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习
如果你有需要的话,可以点赞+评论+转发,关注我,然后私信我【进阶】我发给你
本文暂时没有评论,来添加一个吧(●'◡'●)