1.Retrofit是什么
retrofit是什么,Retrofit
是square
公司全家桶中的一员,基于OkHttp二次封装的网络请求框架,使用了大量注解进行封装。
2.Retrofit优点,为什么使用它
上面说到retrofit是基于OkHttp封装的,那么为什么要使用它呢,它有以下优点:
- 基于OkHttp,继承了OkHttp的优点,拥有socket连接池
- 使用了注解,使得接口的定义跟接口的使用解耦
- 提供了convert转换器,可以快速进行各种数据转换
- 可以集成rxjava,使得异步请求不必要考虑更多操作
通过上面这么多优点介绍,我们还有不使用它的理由吗?
话不多说,先上示例代码,通过示例代码带大家了解retrofit。
3.示例代码
这是网络接口定义
import okhttp3.ResponseBody
import retrofit2.Call
import retrofit2.http.GET
import retrofit2.http.Query
import retrofit2.http.Streaming
import retrofit2.http.Url
interface NetApi {
@GET("getLasterExcelInfo")
fun getLastExcelInfo(@Query("fromType") fromType: Int, @Query("projectType") projectType: Int): Call<BaseResult>
@Streaming
@GET
fun downloadExcel(@Url url: String): Call<ResponseBody>
}
//1.创建retrofit对象
var retrofit: Retrofit = Retrofit.Builder()
.baseUrl("http://...")
.addConverterFactory(GsonConverterFactory.create())
.build()
var netApi = retrofit.create(NetApi::class.java)
var call = netApi.getLastExcelInfo(1, 1)
call.enqueue(object : Callback<BaseResult> {
override fun onFailure(call: Call<BaseResult>?, t: Throwable?) {
println("失败")
}
override fun onResponse(call: Call<BaseResult>?, response: Response<BaseResult>?) {
var response = response?.body()
println("成功" + response.toString())
}
})
netApi.downloadExcel("http://...")
.enqueue(object : Callback<ResponseBody> {
override fun onFailure(call: Call<ResponseBody>?, t: Throwable?) {
println("下载文件失败")
}
override fun onResponse(call: Call<ResponseBody>?, response: Response<ResponseBody>?) {
println("下载文件成功")
var inputStream = response?.body()?.byteStream()
var file = File("F://libraryquestions_1_1_1.xls")
var os = FileOutputStream(file)
var ch: Int?
while (((inputStream?.read()).also { ch = it }) != -1){
if (ch != null)
os.write(ch!!)
}
os.flush()
os.close()
}
})
上面是retrofit的简单使用,一个是get请求,一个为下载文件。是用kotlin写的,如果大家不熟悉kotlin可以略过不看,不影响我们对retrofit的源码简单分析。
那么通过上面可以总结出retrofit使用三步走:
- .构建retrofit对象,主要是运用构造者模式,设置baseurl、数据解析器、设置okhttpclient等。
- 通过动态代理模式获取功能接口对象
- 通过功能接口对象invoke方法返回Call对象执行enqueue、execute方法
4.源码分析
开始我们的主题,通过上面大家对retrofit有了基本认识,下面我们通过retrofit三步走来分析源码。
首先我们分析第一步生成retrofit
我给大家转成java代码
Retrofit retrofit = new Retrofit.Builder() .baseUrl("") .addConverterFactory(GsonConverterFactory.create()) .build();
通过如上图所示,内部是实现了构建者模式,进行各种设置baseurl、转换器、okhttpclient(没有设置的话会新建一个)等,这部分代码大家可以自己点击进去查看,很简单。
下面给大家分析第二步,很重要,动态代理生成接口类
大家注意我勾选的俩部分,其中
Proxy.newProxyInstance(service.getClassLoader()运用了动态代理技术返回不同的接口service实例,大家不明白动态代理的可以参考我下一篇文章。
下面这一步很重要
ServiceMethod serviceMethod = loadServiceMethod(method);
大家注意这句代码,我们进去是下面这段代码
ServiceMethod loadServiceMethod(Method method) {
ServiceMethod result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
result = new ServiceMethod.Builder(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
我进入result = new ServiceMethod.Builder(this, method).build();这个build中
上面我们进入了这个方法里面,大家是不是很熟悉,这正是我们的接口service上面的注解,
所以通过上面的分析,大致就是通过动态代理,反射拿到类class对象,然后通过获取类的注解上面的值,进行各种判断,获取参数等生成request对象。
private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
//生成reqesut跟call对象,在OkHttpCall实体中
然后第三步,将运用service接口对象调用方法返回call对象调用enqueue跟execute方法
上面只是个人通过查看retrofit源码了解到的,大家不喜勿喷,欢迎留言评论,指出不足之处!!!