这是我参与「第四届青训营 」笔记创作活动的第7天 今天的内容是基于Retrofit的网络通讯
网络通信
网络请求框架对比:
- HttpURLConnection
- Volley
- 停更
- 不适合上传下载文件
- OkHttp
- 支持大文件上传下载
- 性能更好
- 一般需要二次封装
- Retrofit
- 可以通过注解配置请求
- 可以搭配转换器解析数据,支持jackjson,pb等
Retrofit简介
Retrofit其实是对OkHttp的一个封装,使用Retrofit库的基本流程包括引用、创建用于描述网络请求的接口、使用Retrofit实例发起网络请求。
场景:客户端知道用户uid,要在服务端查询用户姓名,通过Retrofit实现
- 接口:
https://www.bytedane.com/{uid}/name - 类型:GET请求
- 接口返回:
{
"message": "success",
"data" : {
"uid": "1123",
"first_name":"张",
"last_name":"三丰"
}
}
1.导入dependencies依赖
dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.4.0'
}
2.创建用于描述网络请求的接口
interface IUserInfoService {
@GET("users/{uid}/name")
fun getUserName(@Path("uid") uid: Int): Call<ResponseBody>
...
}
- 接口类名:和请求的含义相关
- 函数名:识别出该接口的作用,该Interface里可以增加多个不同的函数
- @GET注解:指定该接口的相对路径,用get方法发起请求
- @Path注解:需要外部调用时,用传入的uid替换注解里的{uid}
- 返回值Call<ResponseBody>:可以直接转换把Sring转换为Model,这里就转换为User
- ResponseBody:根据返回内容定义的类,应当包含所有字段和一些输出方法,
response.body()是该类的一个实例
- 发起网络请求
fun getUserName(View) {
//创建Retrofit实例
val retrofit = Retrofit.Builder()
.baseUrl("https://www.bytedance.com/")//请求Url地址
.build()
//创建 网络请求接口 的实例
val iUserInterface = retrofit.create(IUserInfoService::class.java)
val call = iUserInterface.getUserName(1123)
//入队异步请求
call.enqueue(object: Callback<ResponseBody> {
override fun onResponse(call: Call<ResponseBody>,response: Response<ResponseBody>) {
request_result_tv.text = "请求成功:" + response.body()!!.string();
}
override fun onFailure(call: Call<ResponseBody>, e: Throwable) {
request_result_tv.text = "请求失败" + e.message
}
})
}
Retrofit注解
-
注解简介 注解可以作用在类、方法、参数、成员变量上,并且可以在合适的时机读取注解并进行替换。 注解的处理一般有三个时机(Retention): 1.SOURCE: 只在源码有效 2.CLASS: 编译时用注解处理器处理 3.RUNTIME: 运行时处理
-
注解定义
@Target(METHOD)//作用对象
@Retention(RUNTIME)//生命周期
public @interface GET {
String value() default "";
}
- 注解使用
可以利用Method类的接口来获取注解的内容。配合动态代理可以获取方法和参数的注解,构造Request对象。
public static Object newProxyInstance(ClasslLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
public interface InvocationHandler{
public Object invoke(Object proxy, Method method, Object[] args)
throw Throwable;
}
之后可以通过Method.getAnnotaion()和Method.getParameterAnnotation()来获取方法和方法参数的注解内容。
代码分析
Retrofit的代码
Retrofit retrofit = new Retrofit.builder()
.baseUrl("http://www.bytedance.com/")
.addConverterFactory(GsonConverterFactory.create())//利用gson转换器解析json,需要添加gson依赖
.build();
IUserInfoService iUserInterface = retrofit.create(IUserInfoService.class);
retrofit2.Call<ResponseBody> call = iUserInterface.getUserName(1123);
call.enqueue(new Callback<ResponseBody>() {
@Override
public void onResponse (Call<ResponseBody> call,
Response<ResponseBody> response){
}
@Override
public void onFailure(Call<ResponseBody> call, Throwable t){
}
})
OkHttp的代码
//创建OkHttpClient
OkHttpClient OkHttpClient = new OkHttpClient.Builder().build();
Request request = new Request.Builder()
.get()
.url("https://www.bytedance.com/user/1123/name")
.build();
//
OkHttp.Call call = okHttpClient.newCall(request);
Call.enqueue(new Callback() {
@Override
public void onFailure (Call call, IOException e) {
}
@Override
public void onResponse (Call call, Response response) {
//TODO: 服务器响应结果
}
});
字节跳动网络库
Cronet用C++实现,对OkHttp进行了特定优化。对其进行二次封装,设计一个高已用、功能全面的框架。最终决定基于Retrofit进行二次开发,将底层的OkHttp替换为Cronet,这就是TTNet。 核心点就是将OkHttpClient和OkHttpCall的生成替换为OkHttp和Cronet二选一。