Retrofit源码解析(二)
Retrofit源码解析(三)
在介绍retrofit之前,还是要先详细说一下okhttp。retrofit与okhttp的角色关系就像包工头和工人,retrofit就是包工头,okhttp就是工人。当你想盖一栋房子(发送网络请求)的时候,你就要去和包工头协商我要什么样的房子(发送什么样的请求),当最终确定后,包工头就会派工人去进行实际施工(okhttp去完成实际的网络请求),房子竣工后包工头又来告诉你房子盖完了(retrofit的callback请求回调)。先来看用okhttp发送一个模拟的网络请求:
val okHttpClient = OkHttpClient.Builder().build()
val request = Request.Builder()
.url("http://www.baidu.com/user/login")
.get()
.build()
val call = okHttpClient.newCall(request)
call.enqueue(object : Callback {
override fun onResponse(call: Call, response: Response) {
val responseBody = response.body()
Log.d("请求成功", responseBody.string())
}
override fun onFailure(call: Call, e: IOException) {
Log.d("", e.printStackTrace().toString())
}
})
这里有几个比较重要的角色:okHttpClient、request、call、callback、response、responseBody
okhttpclient:用来创建call对象
request:封装了本次请求的参数信息,是Get还是Post方法等
call:最终由call发起网络请求
callback:okhttp网络请求的回调
response:一次网络请求的响应报文的封装类,例如包含响应header、body等
responseBody:一次网络请求的响应报文中,body的封装类。相当于下边报文中的Json部分
下边放上这次请求的响应报文:
GET /user/login HTTP/1.1
Host: www.baidu.com
Accept-Encoding: gzip
Connection: keep-alive
{
"success": true,
"name": "Tom"
}
最终通过responseBody.string()方法就拿到了一次网络请求最终返回的body的内容的字符串了,通常我们接口都会返回Json数格式的字符串数据,拿到这个数据,我们就可以使用Gson等库进行解析了。看到这里貌似okhttp很简单啊?的确,okhttp已经封装的很简单了,但是还不够优雅,例如okhttp没有做线程的切换,最终的callback是在工作线程完成的。并且每一次请求成功后我们都要自己手动去转换callback中返回的数据等等,所以retrofit就登场了。上边的请求再用retrofit写一遍:
interface Api {
@GET("user/login")
fun login(): Call<ResponseBody>
}
val retrofit = Retrofit.Builder().baseUrl("http://www.baidu.com/").build()
val api = retrofit.create(Api::class.java)
val call = api.login();
call.enqueue(object : retrofit2.Callback<ResponseBody> {
override fun onResponse(call:retrofit2.Call<ResponseBody>,response: retrofit2.Response<ResponseBody>) {
val responseBody = response.body()
Log.d("请求成功", responseBody.string())
}
override fun onFailure(call: retrofit2.Call<ResponseBody>, t: Throwable) {
}
})
和okhttp相比貌似retrofit也有两个相同的面孔:call、callback
call:在Api接口中,login方法的返回值是Call,这里的Call并不是okhttp中的Call
package okhttp3;
public interface Call extends Cloneable {
···
}
package retrofit2;
public interface Call<T> extends Cloneable {
···
}
可以看到retrofit并没有直接使用okhttp的Call类,而是自己又定义了一个带有泛型的Call<T>类。这里的泛型T就是最终callback的onResponse方法中返回数据的类型。 所以在默认情况下(没有为retrofit添加自定义的CallAdapterFactory,也没有添加ConverterFactory)时,Api接口中我们定义的方法必须返回 Call<ResponseBody> 类,否则会抛出异常,并且此时callback的onResponse方法中返回的类型就是Response<ResponseBody>类型的。但是这个我们后边再说。
callback:与call类似,retrofit同样定义了自己的callback类:
package okhttp3;
public interface Callback {
···
}
package retrofit2;
public interface Callback<T> {
···
}
上边的retrofit实现中,我们没有为retrofit设置GsonConverterFactory,所以此时retrofit并不具备自动将Json数据实例化的能力。所以在login方法中的返回值是Call<ResponseBody>,并且在最终callback的onResponse方法中得到了responseBody,这个ResponseBody类就是okhttp中的类,retrofit并没有再重新定义。所以最终的结果貌似和okhttp中是一样的都拿到了请求响应的ResponseBody,但其实不然,retrofit中callback的onResponse方法是执行在UI线程的,这里的线程转换是retrofit帮我们做的,至于是如何实现的后边再说。
总结
这篇文章对比了okhttp和默认的retrofit请求网络流程的大致区别,这只是一个开始,为后边retrofit的解析做铺垫,下一篇将解析retrofit的内部成员和功能。