Retrofit源码解析(二)
来源:互联网 发布:黑格尔的哲学思想知乎 编辑:程序博客网 时间:2024/05/17 21:43
上节课我们留个问题咩有解决,ExecutorCallAdapterFactory这个类是用来干什么的?
老规矩,让我们查看源码!
ExecutorCallAdapterFactory(Executor callbackExecutor) { this.callbackExecutor = callbackExecutor;//拿到执行器 }
@Override public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { if (getRawType(returnType) != Call.class) { return null; } final Type responseType = Utils.getCallResponseType(returnType); return new CallAdapter<Object, Call<?>>() { @Override public Type responseType() { return responseType; } @Override public Call<Object> adapt(Call<Object> call) { return new ExecutorCallbackCall<>(callbackExecutor, call);//这个接口很重要,代理和回调的桥接器,我会在下一节继续讲 } }; }
@Override public void enqueue(final Callback<T> callback) { checkNotNull(callback, "callback == null"); delegate.enqueue(new Callback<T>() { @Override public void onResponse(Call<T> call, final Response<T> response) { callbackExecutor.execute(new Runnable() { @Override public void run() { if (delegate.isCanceled()) { // Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation. callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled")); } else { callback.onResponse(ExecutorCallbackCall.this, response); } } }); } @Override public void onFailure(Call<T> call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(ExecutorCallbackCall.this, t); } }); } }); }
看到这个enqueue方法我相信使用过Retrofit的朋友们的疑惑都消除了,其实就是执行了异步操作但是通过执行器在主线程中修改UI界面。
也就是说Runnable里面的代码是在主线程中进行的,所以是可以在这里修改UI线程的!
也就是说Runnable里面的代码是在主线程中进行的,所以是可以在这里修改UI线程的!
也就是说Runnable里面的代码是在主线程中进行的,所以是可以在这里修改UI线程的!
说的更加通俗点就看下面的代码:
Call<ResponseBody> call=RetrofitUtils.getInstance().getApiService().getCompleteBook(); call.enqueue(new Callback<ResponseBody>() { @Override public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) { //主线程中进行的,可以修改UI界面 try { toast(response.body().string().toString()); } catch (IOException e) { e.printStackTrace(); } } @Override public void onFailure(Call<ResponseBody> call, Throwable t) { //主线程中进行的,可以修改UI界面 } });
前面基本上把Retrofit构建和异步操作原理讲明白了,但是还有一个大家疑惑的地方在于我定义Retrofit的时候一般需要一个接口,里面写满了各种各样的带注解的方法,但是Retrofit是如何把GET,POST这样的请求辨识出来并且封装成一个Call的呢?
动态代理
让我们看一个例子:
public interface ApiService { @Getter String showTeacherName(String name); @Setter String showStudentName(String name);}
public class Main { public static void main(String[] args) { ApiService api= (ApiService) Proxy.newProxyInstance(ApiService.class.getClassLoader(), new Class[]{ApiService.class}, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(args[0].toString()); Annotation[] annotations = method.getAnnotations(); System.out.println(annotations[0].annotationType()); return args[0].toString(); } }); api.showStudentName("张三"); api.showTeacherName("刘老师"); }}
结果如图所示:
这里简单讲下动态代理的好处,动态代理和静态代理不同,不需要提前编译所以编译之前不会产生字节码,不占用内存;程序异常灵活省去大量重复写代码的时间;可以修改代码执行的内容,可以在方法调用前后增加自己的内容。但是在本文中最重要的是下面这一点
我们仔细观察这个接口里面的方法,注解是不一样的,GET SET,如果按照以前的思路,动态代理里面的方法都必须调用method.invoke(**),因为是要考虑不同的返回类型,但是这里遇到了一种极端状况,返回类型都一样!都是String,所以我们其实可以自定义返回的值,举个例子,我给别人写信,给我的爸爸妈妈,兄弟姐妹写的话我会分别写:亲爱的老爸,亲爱的老妈,亲爱的老弟等等,但是如果现在我只给我的女朋友写信,我就写:Dear Love,就不会再具体情况具体分析了,全部都是一样的。
举这个例子是为了做个铺垫,下一节我会详细讲述Retrofit是如何按照这个思路来封装Call的,我们下节课见。
- Retrofit源码解析(二)
- 【Retrofit】Retrofit源码解析
- android网络框架retrofit源码解析二
- 超详细Retrofit源码解析(二)
- Retrofit源码解析
- Retrofit源码解析
- Retrofit源码解析
- Retrofit源码解析
- Retrofit源码解析
- Retrofit源码解析
- Android Retrofit源码解析
- Retrofit 源码解析
- Retrofit源码解析
- Retrofit源码解析:RxJavaCallAdapterFactory
- Retrofit源码解析---初始化
- Retrofit 源码解析
- Retrofit源码解析
- Retrofit源码解析
- v撒
- Servlet随机生成验证图片
- 1004 Max Sum
- Python-单下划线与双下划线的区别
- java并发编程实战-显式锁
- Retrofit源码解析(二)
- Qt for Android获取手机序列号/手机型号/手机制造商
- 函数返回局部变量
- nginx启动重启与升级以及检测配置文件
- 1055. The World's Richest 解析
- 基于bootstrap的web登陆实例
- 二分搜索
- caffe学习之二----mnist集合训练及其测试
- Flask学习笔记-- 4