从一个最简单的例子来看Retrofit(一)
来源:互联网 发布:图像处理相关算法 编辑:程序博客网 时间:2024/05/23 13:16
- Demo
- 代码分析
- Retrofit 初始化
本文将从Retrofit 官网上提供的一个简单的例子来大致看一下Retrofit的代码
Demo
interface:
@GET("/repos/{owner}/{repo}/contributors") Call<List<Contributor>> contributors(@Path("owner") String owner, @Path("repo") String repo);
retrofit 网络请求,异步:
Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .build(); GitHubService service=retrofit.create(GitHubService.class); Call<List<Contributor>> repos = service.contributors("square", "retrofit"); repos.enqueue(new Callback<List<Contributor>>() { @Override public void onResponse(Call<List<Contributor>> call, Response<List<Contributor>> response) { List<Contributor> contributors = response.body(); for (Contributor contributor : contributors) { System.out.println(contributor.login + " (" + contributor.contributions + ")"); } } @Override public void onFailure(Call<List<Contributor>> call, Throwable t) {} });
这是Retrofit 提供的一个最简单的Demo,运行结果就不展示了。
代码分析
Retrofit 初始化
retrofit 可以通过构造体初始化,也可以通过Retrofit的内部类Builder class 进行初始化,首先说明Builder创建Retrofit这种设计模式不是建造者模式,而是门面模式。有时间可以写一篇门面模式的博客。,其实这种形式在android中挺常见,包括AlertDialog 初始化。这种形式的好处在于:
- 流式调用模式,代码更加清晰
下面开始分析一下Retrofit的代码
首先Builder 构造体中通过Platform的findPlatform()方法决定当前代码的运行平台。
private static Platform findPlatform() { try { Class.forName("android.os.Build"); if (Build.VERSION.SDK_INT != 0) { return new Android();//如果是android设备SDK版本肯定不为0 } } catch (ClassNotFoundException ignored) { } try { Class.forName("java.util.Optional"); return new Java8(); } catch (ClassNotFoundException ignored) { } return new Platform(); }
同时Platform 提供defaultCallbackExecutor 方法,该方法是决定异步网络请求回调线程。我们都知道Android 中网络回调是在主线程上(更新UI),看一下Android 代码:
static class Android extends Platform { @Override public Executor defaultCallbackExecutor() { return new MainThreadExecutor(); } @Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) { if (callbackExecutor == null) throw new AssertionError(); 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); } } }
在Android类中复写了defaultCallbackExecutor ,defaultCallAdapterFactory方法。我们知道android 中网络请求是不允许在主线程上的,而UI 更新是必须在主线程上。我们常见网络请求就是为了更新UI,所以我们需要一个回调将网络线程上请求的数据,发送到主线程上,所以在retrofit中callBack(回调) 通过获取主线程Handler将信息传递出去,这样就确保Retrofit 回调在主线程上。
而 defaultCallAdapterFactory 这个方法为什么要将callBack参数传递?ExecutorCallAdapterFactory,根据这个类名我们也大概知道这是一个CallAdapter的工厂类,代码如下:
ExecutorCallAdapterFactory
@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); } }; }
通过阅读代码可以看到是通过get方法返回CallAdapter对象,ExecutorCallAdapterFactory里面有一个内部类ExecutorCallbackCall,它初始化的时候真正的用到了callbackExecutor ,
static final class ExecutorCallbackCall<T> implements Call<T> { final Executor callbackExecutor; final Call<T> delegate; ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) { this.callbackExecutor = callbackExecutor; this.delegate = delegate; } @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()) { 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 这个方法, 我会想到OKHttp中的异步请求,其实还真是这样,我们知道Retrofit 网络请求默认是通过Okhttp进行网络请求的,在请求网络结束之后分别有两个方法回调,onResponse 和 onFail ,这两个方法的回调信息都是callbackExecutor.execute 发送的,也就是通过handler 将信息发送出去。到这Platform这个类就算说完了,平台不同相应回调实现也不会不同。
好了,Builder的构造体看完了,接着看Builder的方法。通过流式布局的形式,通过调用相应的方法给Retrofit中的变量,最后通过build() 创建出Retrofit对象。
看一下Builder中的方法:
- public Builder baseUrl(HttpUrl baseUrl) //设置网络请求地址
- public Builder addConverterFactory(Converter.Factory factory) //转换工厂 (GsonConverterFactory , RxJava2CallAdapterFactory)
- public Builder addCallAdapterFactory(CallAdapter.Factory factory)
- public Builder callbackExecutor(Executor executor) //回调执行器
- public Builder client(OkHttpClient client)
public Retrofit build() { if (baseUrl == null) { throw new IllegalStateException("Base URL required."); } okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } Executor callbackExecutor = this.callbackExecutor; if (callbackExecutor == null) { callbackExecutor = platform.defaultCallbackExecutor(); } // Make a defensive copy of the adapters and add the default Call adapter. List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor)); // Make a defensive copy of the converters. List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories); return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); }
其中Call.Factory 是通过client() 赋值的,如果未通过该方法赋值,则会使用默认OkhttpClient 。Retrofit的初始化就到这!
- 从一个最简单的例子来看Retrofit(一)
- 从一个最简单的例子来看Retrofit(二)
- Servlet一个最简单的例子(一)
- 从一个小例子来看setInterval的使用
- 用一个简单的例子来看MIDlet的生命周期
- Retrofit实战(一)一个简单的示例
- 一个极简单的Retrofit和RxJava的小例子
- 一个简单可复用的MVP+RxJava+Retrofit例子
- 一步一步从入门到精通(一)建立一个简单入门的例子
- Android5.0 显示系统(一)————从一个简单的例子开启
- 一个最简单的ClassLoader的例子
- winsocket 的最简单的一个例子
- 一个最简单的Makefile例子(转)
- Struts2学习笔记(二):最简单的一个例子
- MFC:一个最简单的例子
- 一个最简单的ajax例子
- 一个最简单的泛型例子
- 一个最简单的Socket通信例子
- PHP环境下Memcache的使用方法
- 文章标题
- spark 进程
- acmcoder简单计算
- Unity_FPS游戏_Boss模块流程_01
- 从一个最简单的例子来看Retrofit(一)
- 人生永远没有太晚的开始
- C++动态申请二维数组
- 简易Web服务器
- hibernate持久化对象的四个状态
- 关于技术和产品的一些体会
- NOIP复赛模板及技巧积累(不定期更新)
- 【排序算法大合集】
- 查看CDH各组件版本