基础介绍
Retrofit 是对okhttp的封装,使用了大量的设计模式,核心原理:运行期,JDK动态代理。Retrofit官网
JDk动态代理实现步骤
- 新建接口类,添加接口方法(不继承其他接口)
- 新建接口实现类,实现接口
- 新建代理类实现反射包java.lang.reflect.InvocationHandle的invoke方法,接口类的实现都由invoke代理,可在方法前后添加补充操作等。
Retrofit简单例子使用
1:添加网络权限
<uses-permission android:name="android.permission.INTERNET" />
2:添加依赖:
implementation 'com.squareup.retrofit2:retrofit:2.6.1'
implementation 'com.squareup.retrofit2:converter-gson:2.6.1'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.6.1'
3:基本使用
A:新建接口类(通过用户类型返回用户集合)
public interface GithubService {
@GET("users/{user}/repos")
Call<List<User>> listRepos(@Path("1") String userType);
}
B:简单使用:
User user =new User();
user.setType("1");
Retrofit retrofit =new Retrofit.Builder()
//基本地址,和接口注解的地址拼接成完整的请求地址
.baseUrl("https://api.xxx.com/")
//数据转换工厂
.addConverterFactory(GsonConverterFactory.create())
//请求call适配器,如将使用Rxjava
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
//接口实例(通过jdk动态代理)
GithubService githubService =retrofit.create(GithubService.class);
githubService.listRepos(user.getType()).enqueue(new Callback<List<User>>() {
@Override
public void onResponse(Call<List<User>> call, Response<List<User>> response) {
}
@Override
public void onFailure(Call<List<User>> call, Throwable t) {
}
});
Retrofit部分源码分析
使用上面的简单例子分析:基本解析为代码上的注释
1:通过构建者模式创建Retrofit对象
A: 点击Retrofit先大致看下Retrofit的属性
Retrofit retrofit =new Retrofit.Builder().build();
public final class Retrofit {
//缓存ServiceMethod网络请求方法
private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();
//网络请求Call,默认为Okhtp的Call
final okhttp3.Call.Factory callFactory;
//网络请求地址
final HttpUrl baseUrl;
//类型转换工厂集合,将返回的ResponseBody转换成java对象,即请求方法的返回类型
final List<Converter.Factory> converterFactories;
//请求CAll转换工厂,将Retrofit的Call转换成其他请求的CAll,如Rxjava
final List<CallAdapter.Factory> callAdapterFactories;
//线程调度器,子线程执行完网络请求,切换成回UI显示就是使用此对象
final @Nullable Executor callbackExecutor;
//迫切验证标志位,提前完成ServiceMethod
final boolean validateEagerly;
.....
}
B:进入Builder(),只是一个平台适配,如Android 、Java8等
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
try {
Class.forName("java.util.Optional");
return new Java8();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
C:进入build()
此处调用Retrofit的构造方法进行创建Retrofit对象,没有添加转换等工厂的话则使用默认的
2:Retrofit重点 在运行期通过jdk动态代理进行接口实现类创建,查看retrofit.create方法
GithubService githubService =retrofit.create(GithubService.class);
public <T> T create(final Class<T> service) {
//1:service.isInterface()检验定义的接口是否是借口类型
//2:service.getInterfaces().length > 0 校验是否是单纯的接口,未继承其他接口
Utils.validateServiceInterface(service);
//是否需要提前解析接口中的请求方法
if (validateEagerly) {
//先从缓存Map serviceMethodCache 中查找,没有的话则通过parseAnnotations方法生成
//ServiceMethod(ServiceMethod位包含所有请求信息的方法对象)
eagerlyValidateMethods(service);
}
//getClassLoader 将.java转为.class
//new Class<?>[] { service } 前面定义的接口文件
//InvocationHandler 通过实现invoke方法 实现前面接口的内方法
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
private final Object[] emptyArgs = new Object[0];
@Override public @Nullable Object invoke(Object proxy, Method method,
@Nullable Object[] args) throws Throwable {
// If the method is a method from Object then defer to normal invocation.
//如果是默认的方法toString()等则直接调用实现
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
//平台默认方法 platform.isDefaultMethod(method) 点击进入直接返回就是false
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
//重点方法
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
3: loadServiceMethod(method)方法创建ServiceMethod
读取接口中的方法转换成ServiceMethod,前面的迫切validateEagerly也是调用这个方法
ServiceMethod<?> loadServiceMethod(Method method) {
//先从缓存map中查找
ServiceMethod<?> result = serviceMethodCache.get(method);
if (result != null) return result;
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
//缓存中没有则通过parseAnnotations转换成拥有所有请求信息的方法对象ServiceMethod,继而放入缓存map
result = ServiceMethod.parseAnnotations(this, method);
serviceMethodCache.put(method, result);
}
}
return result;
}
4: 查看invoke方法
loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
@Override final @Nullable ReturnT invoke(Object[] args) {
//得到retrofit2.Call对象 ,用于之后网络请求enqueue等方法的使用
Call<ResponseT> call = new OkHttpCall<>(requestFactory, args, callFactory, responseConverter);
//通过这个adapt 将call转换成新的retrofit.call对象,如rxjava的obervable等
//使用这个call调用同步异步网络请求方法时,通过ServiceMethod相关创建一个Okhttp3的CAll对象来实现请求
//由后台发起网络请求,返回后再主线程调用回调方法,实现线程切换(callbackExecutor)
return adapt(call, args);
}
5:最后调用同步异步方法就是将使用okhttp3的Call对象进行网络请求
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
okhttp3.Call call;
......
if (call == null && failure == null) {
try {
//创建Okhttp3的CAll对象
call = rawCall = createRawCall();
} catch (Throwable t) {
throwIfFatal(t);
failure = creationFailure = t;
}
}
......
//okhttp3的CAll进行请求网络
call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
throwIfFatal(e);
callFailure(e);
return;
}
......
});
}