Retrofit的使用
1.创建网络请求的接口
public interface GetApi {
/**
* 获取用户信息
* @return
* @Query 注解
*/
@GET("getUserInfo")
Call<UserInfo> getUserInfo(@Query("id") String userId);
}
2. 创建Retrofit实例
private Retrofit retrofit;
retrofit = new Retrofit.Builder()
.baseUrl("http://mock-api.com/2vKVbXK8.mock/")
.addConverterFactory(GsonConverterFactory.create()) //返回的Json数据进行解析
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
使用构造者模式
addConverterFactory(GsonConverterFactory.create())
添加转换器工厂,以支持不同的数据模式。
addCallAdapterFactory(RxJava2CallAdapterFactory.create())
添加网络请求的适配器,支持RxJava
3.创建网络请求接口的实例
private GetApi getApi;
getApi = retrofit.create(GetApi.class);
4.发送网络请求,处理服务器返回的数据
getApi.getUserInfo(userid).enqueue(new Callback<UserInfo>() {
@Override
public void onResponse(Call<UserInfo> call, Response<UserInfo> response) {
if (response != null && response.body() != null) {
//此处为获取到的信息
UserInfo userInfo = response.body();
}
}
@Override
public void onFailure(Call<UserInfo> call, Throwable t) {
Log.i(TAG, "onFailure: " + t);
}
});
这是一个完整的Retrofit请求的过程。
Retrofit真正的网络请求工作是交给okhttp去完成的,retrofit是专注于接口的封装。
使用动态代理将注解翻译成一个一个okhttp请求。最后由线程池来执行okhttp请求。
动态代理的知识
什么叫代理模式
代理模式:为其他对象提供一种代理,用以控制这个对象的访问。海外购物的时候找代购帮我们买东西,代购怎么买的过程我们不需要关心,我们只在意结果。
静态代理
有一个学生管理类,提供了“添加学生”和“删除学生”两个方法:
public interface IStudentService {
void insertStudent();
void deleteStudent();
}
public class StudentService implements IStudentService {
public void insertStudent(){
//添加学生
}
public void deleteStudent(){
//删除学生
}
}
如果我们想要在添加/删除的前后分别打上日志,应我们该怎么做呢?
public class StudentService implements IStudentService {
public void insertStudent(){
System.out.println("准备添加学生");
//添加学生
System.out.println("添加学生成功");
}
public void deleteStudent(){
System.out.println("准备删除学生");
//删除学生
System.out.println("删除学生成功");
}
}
如果过两天,我们又打算在添加/删除方法上添加事务呢?
这样又需要修改添加/删除方法,我们要遵循对扩展开放,对修改封闭,此外,日志和事务不属于学生管理类的业务范畴,交给专门的类来处理。
如此一来代理就排上了用场,无论是日志还是事务可以交给代理类来解决。
public class StudentServiceProxy implements IStudentService {
IStudentService studentService;
public StudentServiceProxy(IStudentService studentService){
this.studentService = studentService;
}
@Override
public void insertStudent() {
System.out.println("准备添加学生");
studentService.insertStudent();
System.out.println("添加学生成功");
}
@Override
public void deleteStudent() {
System.out.println("准备删除学生");
studentService.deleteStudent();
System.out.println("删除学生成功");
}
}
在上面的代码中,代理类和业务类继承了相同的接口,并且重写了添加/删除学生的方法。
在重写的方法中,我们不仅可以调用业务类的原有方法,并且在调用的前后可以进行额外的处理,比如加上日志、事务等等。
这样一来,在客户端当中,我们只要创建了代理类,就可以像使用业务类一样使用它,非常方便:
public class Client {
public static void main(String[] args) {
IStudentService studentServiceProxy = new StudentServiceProxy(new StudentService());
studentServiceProxy.insertStudent();
studentServiceProxy.deleteStudent();
}
}
像这样通过代理类给对象的行为添加辅助功能的解决方案,就是代理模式。
如果我们要对已有的方法做改进,有2种选择,第一种是去修改原来的方法,第二种就是使用代理类,调用原来的方法,对产生的结果进行控制。不修改原来的方法的情况下,增强方法和功能。
动态代理
如果有许多的类都需要增加日志,比如学生管理类、教师管理类、物资管理类、难道要给每一个业务类都配一个代理类吗?
如果需要灵活的代理,我们需要做到动态代理。
所谓动态代理,在程序运行时创建的代理方式
以Java语言为例,Java为我们提供了十分方便的创建动态代理的工具包。当我们生成动态代理的时候,我们需要使用到InvocationHandler接口和Proxy类。
具体的实现过程如下:
1.实现InvocationHandler接口,定义调用方法前后所做的事情:
public class MyInvocationHandler implements InvocationHandler {
private Object object;
public MyInvocationHandler(Object object){
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + "方法调用前");
method.invoke(object, args);
System.out.println(method.getName() + "方法调用后");
return null;
}
}
2.通过Proxy类的newProxyInstance方法,动态生成代理对象:
public class Client {
public static void main(String[] args) {
IStudentService studentService = new StudentService();
InvocationHandler studentInvocationHandler = new MyInvocationHandler(studentService);
IStudentService studentServiceProxy = (IStudentService) Proxy.newProxyInstance(studentInvocationHandler.getClass().getClassLoader(), studentService.getClass().getInterfaces(), studentInvocationHandler);
studentServiceProxy.insertStudent();
studentServiceProxy.deleteStudent();
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
return null;
}
proxy:代理的真实对象
method:调用的真实对象的某一个方法
args:代理真实对象的某一个方法的所有参数
为什么要这么做?
生成相对应的代理类,会调用invoke方法
接下来看看Retrofit 源码
public final class Retrofit {
private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
private final okhttp3.Call.Factory callFactory;
private final HttpUrl baseUrl;
private final List<Converter.Factory> converterFactories;
private final List<CallAdapter.Factory> adapterFactories;
private final Executor callbackExecutor;
private final boolean validateEagerly;
七个关键成员变量的作用
serviceMethodCache: 缓存
callFactory : 生产OKHttpClient
baseUrl : 基地址
converterFactories: 数据转换器的工厂的集合 ,数据请求之后的response的转换,转换成我们能用的对象
adapterFactories: 网络适配器的工厂 生产CallAdapter RXJava
callbackExecutor : 执行回调 网络请求最终都是通过线程池加handler来进行调配的,能处理子线程和主线程切换的
validateEagerly: 标志位是否需要立即解析接口中的方法
构建者模式对成员变量的初始化
public static final class Builder {
private Platform platform;
private okhttp3.Call.Factory callFactory;
private HttpUrl baseUrl;
private List<Converter.Factory> converterFactories = new ArrayList<>();
private List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
private Executor callbackExecutor;
private boolean validateEagerly;
Builder(Platform platform) {
this.platform = platform;
}
public Builder() {
this(Platform.get());
}
静态内部类Builder
platform 适用的平台这里是Android
callFactory 请求网络的okhttp的工厂
converterFactories: 数据转换器的工厂集合 网络上获取的response转换成能用的json对象
adapterFactories: 网络请求适配器的工厂集合 call对象转换成Rxjava
callbackExecutor 异步回调的,默认是主线程的Executor,切换线程
看无参的Builder(),Platform 是单例
class Platform {
private static final Platform PLATFORM = findPlatform();
static Platform get() {
return PLATFORM;
}
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) {
}
try {
Class.forName("org.robovm.apple.foundation.NSObject");
return new IOS();
} catch (ClassNotFoundException ignored) {
}
return new Platform();
}
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
通过反射 加载指定的类, 返回一个安卓对象
介绍Android类
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}
static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
private final Handler handler = new Handler(Looper.getMainLooper());
Looper.getMainLooper()和主线程绑定
executor线程切换 回调方法在主线程.这个executor和我们的主线程所绑定了,就是可以在主线程中切换的原因
总结下:
1.配置平台类型的对象 Android
2.配置网路适配器的工厂 和数据转换器的工厂
3.executor
private Retrofit retrofit;
retrofit = new Retrofit.Builder()
.baseUrl("http://mock-api.com/2vKVbXK8.mock/")
.addConverterFactory(GsonConverterFactory.create()) //返回的Json数据进行解析
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
看看这里的 .baseUrl()做了哪些事情
主要是将String类型的baseUrl转换成HttpUrl类型的baseUrl
public Builder baseUrl(String baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
HttpUrl httpUrl = HttpUrl.parse(baseUrl);
if (httpUrl == null) {
throw new IllegalArgumentException("Illegal URL: " + baseUrl);
}
return baseUrl(httpUrl);
}
public Builder baseUrl(HttpUrl baseUrl) {
checkNotNull(baseUrl, "baseUrl == null");
List<String> pathSegments = baseUrl.pathSegments();
if (!"".equals(pathSegments.get(pathSegments.size() - 1))) {
throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);
}
this.baseUrl = baseUrl;
return this;
}
判断最后一个是否以斜杠来结尾
private Retrofit retrofit;
retrofit = new Retrofit.Builder()
.baseUrl("http://mock-api.com/2vKVbXK8.mock/")
.addConverterFactory(GsonConverterFactory.create()) //返回的Json数据进行解析
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
看看这里的addConverterFactory()做了哪些操作
public Builder addConverterFactory(Converter.Factory factory) {
converterFactories.add(checkNotNull(factory, "factory == null"));
return this;
}
看下GsonConverterFactory.create()
public static GsonConverterFactory create() {
return create(new Gson());
}
public static GsonConverterFactory create(Gson gson) {
if (gson == null) throw new NullPointerException("gson == null");
return new GsonConverterFactory(gson);
}
private GsonConverterFactory(Gson gson) {
this.gson = gson;
}
使用gson来解析网络response的数据
private Retrofit retrofit;
retrofit = new Retrofit.Builder()
.baseUrl("http://mock-api.com/2vKVbXK8.mock/")
.addConverterFactory(GsonConverterFactory.create()) //返回的Json数据进行解析
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build();
来看下.addCallAdapterFactory(RxJavaCallAdapterFactory.create())做了哪些操作
public Builder addCallAdapterFactory(CallAdapter.Factory factory) {
callAdapterFactories.add(Objects.requireNonNull(factory, "factory == null"));
return this;
}
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
private final @Nullable Scheduler scheduler;
private final boolean isAsync;
}
RxJava中的调度器Scheduler
了解下build方法完成retrofit对象的创建流程
public Retrofit build() {
//baseUrl不能缺
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
//可以看出retrofit是用OKHttp来完成网络请求的
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
//提供默认的回调方法执行器,异步请求的时候,子线程做耗时操作,要回到主线程做UI操作
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 添加默认的网络请求适配器
List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);
callAdapterFactories.addAll(platform.defaultCallAdapterFactories(callbackExecutor));
// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(
1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());
// Add the built-in converter factory first. This prevents overriding its behavior but also
// ensures correct behavior when using converters that consume all types.
converterFactories.add(new BuiltInConverters());
converterFactories.addAll(this.converterFactories);
converterFactories.addAll(platform.defaultConverterFactories());
return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),
unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);
}
以上就完成了Retrofit的初始化的过程。
RxJavaCallAdapterFactory内部构造与工作原理
public final class RxJava2CallAdapterFactory extends CallAdapter.Factory {
}
public interface CallAdapter<R, T> {
Type responseType();
T adapt(Call<R> call);
abstract class Factory {
public abstract @Nullable CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
//获取原始类型
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
}
}
网络请求接口实例解析
public interface GetApi {
@GET("getUserInfo")
Call<UserInfo> getUserInfo(@Query("id") String userId);
}
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
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.
if (method.getDeclaringClass() == Object.class) {
return method.invoke(this, args);
}
if (platform.isDefaultMethod(method)) {
return platform.invokeDefaultMethod(method, service, proxy, args);
}
return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);
}
});
}
参考文献:
https://juejin.cn/post/6919816939233607694
https://juejin.cn/post/6885358107996717064#heading-12