Retrofit使用及分析
来源:互联网 发布:2017英国大学 知乎 编辑:程序博客网 时间:2024/06/05 06:38
开始使用Retrofit
- 首先先声明一个用于请求的接口
public interface GitHubService { @GET("users/{user}/repos")//执行资源的地址后缀 Call<List<User>> listRepos(@Path("user") String user);}
- 创建一个Retrofit对象,传入一些必要的参数
Converter.Factory factory = GsonConverterFactory.create();//使用Gson来进行数据的解析Retrofit retrofit = new Retrofit.Builder().baseUrl("https://api.github.com/") .addConverterFactory(factory) .build();
- 通过Retrofit对象通过动态代理的形式创建一个对象,发起一个请求。
GitHubService service = retrofit.create(GitHubService.class);Call<List<User>> call = service.listRepos("zhaoyongchao");call.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对象的步骤就是一些赋值,在此只贴出build()的源码
public Retrofit build() { //根路径的判断 if (baseUrl == null) { throw new IllegalStateException("Base URL required."); } //如果不传入,则默认OKHttpClient为默认的请求工厂类 okhttp3.Call.Factory callFactory = this.callFactory; if (callFactory == null) { callFactory = new OkHttpClient(); } // 使用副本,添加默认的适配器 List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories); adapterFactories.add(Platform.get().defaultCallAdapterFactory(callbackExecutor)); // 创建一个用于类型转换的副本 List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories); return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories, callbackExecutor, validateEagerly); } }//区分当前运行的平台(Android)static class Android extends Platform { @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) { if (callbackExecutor == null) { callbackExecutor = new MainThreadExecutor(); } return new ExecutorCallAdapterFactory(callbackExecutor); } static class MainThreadExecutor implements Executor { //使用主线程的Looper来创建一个Handler,用来通信 private final Handler handler = new Handler(Looper.getMainLooper()); @Override public void execute(Runnable r) { handler.post(r); } } }
- 通过Retrofit的Create()方法来创建一个对象
public <T> T create(final Class<T> service) { //判断是否为接口 Utils.validateServiceInterface(service); if (validateEagerly) { eagerlyValidateMethods(service); } //使用Proxy来创建动态创建一个代理对象,使用返回的对象调用接口的方法都会调用匿名内部类的invoke方法。 return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service }, new InvocationHandler() { private final Platform platform = Platform.get(); @Override public Object invoke(Object proxy, Method method, Object... args) throws Throwable { // 判断一下声明的类,如果是Object类,正常执行 if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } if (platform.isDefaultMethod(method)) { return platform.invokeDefaultMethod(method, service, proxy, args); } return loadMethodHandler(method).invoke(args); } }); }
- 调用MethodHandler的creat()方法
static MethodHandler create(Retrofit retrofit, Method method) { //根据方法的注解和返回类型创建具体的实现类,最终会到ExecutorCallAdapterFactory CallAdapter<?> callAdapter = createCallAdapter(method, retrofit); //得到泛型中的类型 Type responseType = callAdapter.responseType(); if (responseType == Response.class || responseType == okhttp3.Response.class) { throw Utils.methodError(method, "'" + Types.getRawType(responseType).getName() + "' is not a valid response body type. Did you mean ResponseBody?"); } //同样创建具体的转换类 Converter<ResponseBody, ?> responseConverter = createResponseConverter(method, retrofit, responseType); //根据请求类型和方法中的注解创建一个请求工厂类 RequestFactory requestFactory = RequestFactoryParser.parse(method, responseType, retrofit); return new MethodHandler(retrofit.callFactory(), requestFactory, callAdapter, responseConverter); }
- createCallAdapter方法最终会调用到Retrofit中的nextCallAdapter方法
public CallAdapter<?> nextCallAdapter(CallAdapter.Factory skipPast, Type returnType, Annotation[] annotations) { checkNotNull(returnType, "returnType == null"); checkNotNull(annotations, "annotations == null"); //使用的是ExecutorCallAdapterFactory int start = adapterFactories.indexOf(skipPast) + 1; for (int i = start, count = adapterFactories.size(); i < count; i++) { CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this); if (adapter != null) { return adapter; } } throw new IllegalArgumentException(builder.toString()); }
- 继续分析一下ExecutorCallAdapterFactory中的get方法
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) { //此适配器只能处理返回类型为Call<?> if (getRawType(returnType) != Call.class) { return null; } //得到Call<T>的泛型T的类型,作为相应体的返回类型 final Type responseType = Utils.getCallResponseType(returnType); return new CallAdapter<Call<?>>() { @Override public Type responseType() { return responseType; } @Override public <R> Call<R> adapt(Call<R> call) { //创建一个对象进行返回 return new ExecutorCallbackCall<>(callbackExecutor, call); } }; }
- createResponseConverter得过程和上述相同不做分析。
- 根据请求类型和方法中的注解创建一个请求工厂类,通过parseMethodAnnotations来解析注解、parsePathParameters来解析注解的值,为工厂类相应的字段赋值。
- 调用创建好的MethodHandler对象的invoke方法,根据上述生成的对象创建OKHttpCall对象也是委派对象,把生成的对象传入ExecutorCallAdapterFactory的adapt方法。
@Override public <R> Call<R> adapt(Call<R> call) { return new ExecutorCallbackCall<>(callbackExecutor, call); }
- 通过返回的Call对象的调用enqueue方法及ExecutorCallbackCall的enqueue方法
//MethodHandler中的方法Object invoke(Object... args) { return callAdapter.adapt( new OkHttpCall<>(callFactory, requestFactory, args, responseConverter)); }@Override public void enqueue(final Callback<T> callback) { //调用及上述根据请求工厂、类型转换工厂和请求参数创建的OkHttpCall对象 delegate.enqueue(new Callback<T>() { @Override public void onResponse(final Call<T> call, final Response<T> response) { //通过handler把回调发送到主线程 callbackExecutor.execute(new Runnable() { @Override public void run() { if (delegate.isCanceled()) { // Emulate OkHttp's behavior of throwing/delivering an IOException on cancelation callback.onFailure(call, new IOException("Canceled")); } else { callback.onResponse(call, response); } } }); } @Override public void onFailure(final Call<T> call, final Throwable t) { callbackExecutor.execute(new Runnable() { @Override public void run() { callback.onFailure(call, t); } }); } }); }
- OkHttpCall中的enqueue方法
@Override public void enqueue(final Callback<T> callback) { okhttp3.Call call; Throwable failure; synchronized (this) { if (executed) throw new IllegalStateException("Already executed."); executed = true; call = rawCall; failure = creationFailure; if (call == null && failure == null) { try { //创建真是的请求 call = rawCall = createRawCall(); } catch (Throwable t) { failure = creationFailure = t; } } } //添加失败回调 if (failure != null) { callback.onFailure(this, failure); return; } if (canceled) { call.cancel(); } //真实的发起请求 call.enqueue(new okhttp3.Callback() { @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse) throws IOException { Response<T> response; try { //解析返回数据 response = parseResponse(rawResponse); } catch (Throwable e) { callFailure(e); return; } callSuccess(response); } @Override public void onFailure(okhttp3.Call call, IOException e) { try { callback.onFailure(OkHttpCall.this, e); } catch (Throwable t) { t.printStackTrace(); } } private void callFailure(Throwable e) { try { callback.onFailure(OkHttpCall.this, e); } catch (Throwable t) { t.printStackTrace(); } } private void callSuccess(Response<T> response) { try { callback.onResponse(OkHttpCall.this, response); } catch (Throwable t) { t.printStackTrace(); } } }); }
- 到目前为止所有的注解和值已经解析,但是没有进行拼接。看一下RequestFactory的creat()方法
Request create(Object... args) throws IOException { RequestBuilder requestBuilder = new RequestBuilder(method, baseUrl.url(), relativeUrl, headers, contentType, hasBody, isFormEncoded, isMultipart); if (args != null) { //从注解中解析的请求类型目前使用的是RequestAction.Path RequestAction[] actions = requestActions; if (actions.length != args.length) { throw new IllegalArgumentException("Argument count (" + args.length + ") doesn't match action count (" + actions.length + ")"); } for (int i = 0, count = args.length; i < count; i++) { actions[i].perform(requestBuilder, args[i]); } } return requestBuilder.build(); }}//RequestAction.Path类中重写的方法@Override void perform(RequestBuilder builder, T value) throws IOException { if (value == null) { throw new IllegalArgumentException( "Path parameter \"" + name + "\" value must not be null."); } builder.addPathParam(name, valueConverter.convert(value), encoded); }//进行完整路径的组合void addPathParam(String name, String value, boolean encoded) { if (relativeUrl == null) { // The relative URL is cleared when the first query parameter is set. throw new AssertionError(); } relativeUrl = relativeUrl.replace("{" + name + "}", canonicalizeForPath(value, encoded)); }//OKHttpClient中的 newCall转换为一个OkHttpCall的真正请求@Override public Call newCall(Request request) { return new RealCall(this, request); }
- 最终的请求在RealCall中
- 在以后还会加入RxJava的组合使用
0 0
- Retrofit使用及分析
- android Retrofit简单使用及源码分析
- Retrofit浅析及使用
- Retrofit简单入门及使用
- Retrofit原理及调用流程分析
- Retrofit原理及调用流程分析
- Retrofit三步理解之三 ------------------ Retrofit完整使用分析
- Retrofit和RxJava结合使用例子分析
- Retrofit网络库使用及解析
- Okhttp插入日志及结合Retrofit使用
- Retrofit的使用,及介绍,Retrofit中的各种方法的详细描述简单案例,三分钟学会Retrofit
- Retrofit分析
- Retrofit使用
- Retrofit使用
- Retrofit使用
- Retrofit使用
- Retrofit使用
- Retrofit使用
- CDOJ 1292 卿学姐种花(分块)
- Ember 翻译——入门一:快速开始
- CSDN验证码的漏洞
- API 25 (Android 7.1.1 API) widget.AbsSpinner
- Android colorPrimary colorPrimaryDark colorAccent
- Retrofit使用及分析
- 通过数据库自动反向生成MyBatis文件
- C++ - 正则表达式(regex) 替换(replace) 的 详解 及 代码
- Heritrix1.14.4 Web后台使用简介
- Android自定义控件实现底部菜单栏
- z-index
- 前端使用html+css,表单型效果自我实现
- apache2: Could not reliably determine the server's fully qualified domain name 解决方法
- centos6.4下keepalived+nginx的高可用(LVS/DR模式)