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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值