美文网首页
1、Retrofit

1、Retrofit

作者: 最美下雨天 | 来源:发表于2018-06-25 08:26 被阅读3次

1、Retrofit与其他网络请求框架的区别?

功能、性能、使用场景

优点:Retrofit基于OkHttp、通过注解来配置请求方法的类型、请求头、请求参数,支持同步、异步请求,可以使用多种Converter对数据进行解析,例如gson、xml,并且支持RxJava。因为OkHttp是基于NIO和Okio的,所以性能更好,请求处理速度都很快。

使用场景:任何场景下优先选择,尤其是项目中运用了RxJava、后台的api遵循了restful风格。

运用到的设计模式:外观模式、构建者模式、动态代理、策略模式

外观模式:将一些复杂的功能进行统一封装,使外部用户更简单的使用,比如Retrofit这个类

构建者模式:比如说Retrofit这个类的实例化

Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://gank.io/")
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();

动态代理:

Api api = retrofit.create(Api.class);
public <T> T create(final Class<T> service) {
    Utils.validateServiceInterface(service);
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    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 {
            // If the method is a method from Object then defer to normal invocation.
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            ServiceMethod serviceMethod = loadServiceMethod(method);
            OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

策略模式:

.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())

这两个操作其实是分别加入到了两个集合中

  private final List<Converter.Factory> converterFactories;
  private final List<CallAdapter.Factory> adapterFactories;

后面对返回的数据进行解析是遍历的converterFactories这个集合,对网络请求进行适配则是遍历adapterFactories这个集合(支持4个),默认这个集合会添加一个,不过在集合末尾

在调用build()方法构建Retrofit实例时

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);
    }

几个重要的变量:

  • callFactory 这儿直接new了OKHttpClient 所以Retrofit是使用了OkHttp
  • callbackExecutor = platform.defaultCallbackExecutor()

我们这里假设没有配置.addCallAdapterFactory(RxJavaCallAdapterFactory.create())

这个callbackExecutor是在网络请求返回数据时进行线程切换的,切换到主线程

static class Android extends Platform {
    @Override public Executor defaultCallbackExecutor() {
      return new MainThreadExecutor();
    }

    @Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
      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);
      }
    }
  }

可以看到这儿的Handler中的looper是从主线程中拿的。

 return serviceMethod.callAdapter.adapt(okHttpCall);

这个callAdapter是从adapterFactories这个集合中遍历获取的

for (int i = start, count = adapterFactories.size(); i < count; i++) {
      CallAdapter<?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
      if (adapter != null) {
        return adapter;
      }
    }

这个集合的初始化

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));
 return serviceMethod.callAdapter.adapt(okHttpCall);

这儿调用adapt()方法

@Override public <R> Call<R> adapt(Call<R> call) {
        return new ExecutorCallbackCall<>(callbackExecutor, call);
      }
 static final class ExecutorCallbackCall<T> implements Call<T> 

这个跟OkHttpCall一样都实现了Call接口,标准的静态代理的写法

ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
final class OkHttpCall<T> implements Call<T> 

所以在请求的时候调用

@Override public void enqueue(final Callback<T> callback) {
      if (callback == null) throw new NullPointerException("callback == null");

      delegate.enqueue(new Callback<T>() {
        @Override public void onResponse(final 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(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);
            }
          });
        }
      });
    }

call.enqueue()发起异步请求时,其实是直接调到这儿来了,在onResponse中直接通过callbackExecutor来切换到主线程

相关文章

网友评论

      本文标题:1、Retrofit

      本文链接:https://www.haomeiwen.com/subject/xzmcyftx.html