从一个最简单的例子来看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的初始化就到这!