美文网首页
Retrofit源码分析

Retrofit源码分析

作者: 骑着乌龟追小兔 | 来源:发表于2018-05-03 18:43 被阅读128次

1.创建retrofit 对象

  Retrofit retrofit = new Retrofit.Builder()
                    .client(okHttpClient)
                    .baseUrl("http://gank.io/api/")
                    .addConverterFactory(gsonConverterFactory)
                    .addCallAdapterFactory(rxJavaCallAdapterFactory)
                    .build();

2.Builder 介绍

  • builder 是用来初始化配置参数的内部类
  • builder 是采用建造者设计模式
  • 在build() 方法调用之前必须调用baseUrl 方法,其他方法都是可选的
builder 成员变量
1. Platform: retrofit 执行的的系统环境,通过findPlatform方法获取是不是是android环境
2. okhttp3.Call.Factory :生成请求的工厂类,默认为okHttpClient
3. baseUrl :HttpUrl 的请求地址
4. List<Converter.Factory> converterFactories:将实体类对象转换成http 传输的对象,或者将http 对象转换成实体类对象
5. List<CallAdapter.Factory> adapterFactories :将返回结果生成指定的类型包装对象

3.创建请求

//创建api 类
public interface GankApi {
    @GET("data/福利/{number}/{page}")
    Observable<GankBeautyResult> getBeauties(@Path("number") int number, @Path("page") int page);
}

    创建api类的请求接口实体类
 retrofit.create(GankApi.class);
create方法介绍:
  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, @Nullable 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<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }
  • 其内部使用了动态代理来实现
ServiceMethod
  • 主要用于处理request 和 response 并将其适配成通过的请求格式
  • 采用了适配器模式,其创建成本很高,所以retrofit 用一个ConcurrentHashMap serviceMethodCache 来保存,网络请求需要注意并发。
   ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
  ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;

    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }
serviceMethod.callAdapter.adapt(okHttpCall)
  • 这段代码主要作用是请求,并返回固定的格式结果
  @Override public Object adapt(Call<R> call) {
    Observable<Response<R>> responseObservable = isAsync
        ? new CallEnqueueObservable<>(call)
        : new CallExecuteObservable<>(call);

    Observable<?> observable;
    if (isResult) {
      observable = new ResultObservable<>(responseObservable);
    } else if (isBody) {
      observable = new BodyObservable<>(responseObservable);
    } else {
      observable = responseObservable;
    }

    if (scheduler != null) {
      observable = observable.subscribeOn(scheduler);
    }

    if (isFlowable) {
      return observable.toFlowable(BackpressureStrategy.LATEST);
    }
    if (isSingle) {
      return observable.singleOrError();
    }
    if (isMaybe) {
      return observable.singleElement();
    }
    if (isCompletable) {
      return observable.ignoreElements();
    }
    return observable;
  }

代理模式

静态代理

主要思路 代理类持有realsubject 对象,可以对相关操作进行拦截。
实例代码如下:

public interface IRunner {
//运动员的主要工作就是跑步
public void run();
}

public class Runner implements IRunner {
public void run() {
System.out.println("运动员跑步: 动作很潇洒");
}
}

public class RunnerAgent implements IRunner {
private IRunner runner;
public RunnerAgent(IRunner _runner){
this.runner = _runner;
}/
/代理人是不会跑的
public void run() {
Random rand = new Random();
if(rand.nextBoolean()){
System.out.println("代理人同意安排运动员跑步");
runner.run();
}else{
System.out.println("代理人心情不好, 不安排运动员跑步");
}
}
}
动态代理

动态生成对象,可以代理方法

InvocationHandler
  • 产生一个对象的代理对象
  • 代理对象在方法被调用的时候被触发
  • 主要场景:面向切面编程
public class GamePlayIH implements InvocationHandler {
    //被代理者
    Class cls =null;
    //被代理的实例
    Object obj = null;
    //我要代理谁
    public GamePlayIH(Object _obj){
    this.obj = _obj;
}
//调用被代理的方法
public Object invoke(Object proxy, Method method, Object[] args)
    throws Throwable {
    Object result = method.invoke(this.obj, args);
    return result;
    }
}

public class Client {
public static void main(String[] args) throws Throwable {
    //定义一个痴迷的玩家
    IGamePlayer player = new GamePlayer("张三");
    //定义一个handler
    InvocationHandler handler = new GamePlayIH(player);
    //开始打游戏, 记下时间戳
    System.out.println("开始时间是: 2009-8-25 10:45");
    //获得类的class loader
    ClassLoader cl = player.getClass().getClassLoader();
    //动态产生一个代理者
    IGamePlayer proxy = (IGamePlayer)Proxy.newProxyInstance(cl,new Class[]{GamePlayer.class},handler);
    //登录
    proxy.login("zhangSan", "password");//开始杀怪
    proxy.killBoss();
    //升级
    proxy.upgrade();
    //记录结束游戏时间
    System.out.println("结束时间是: 2009-8-26 03:40");
    }
}

相关文章

网友评论

      本文标题:Retrofit源码分析

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