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
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 Wi-Fi模块不支持多播怎么办? 魅族手机屏幕点不动怎么办 uc打开网页很慢怎么办 京东手机号码无法登录怎么办 织梦系统网站没收录怎么办 电脑开机出现一堆乱码怎么办 电脑文件夹出现乱码打不开怎么办 电脑出现f1和f2怎么办 电脑中韩文内容显示乱码怎么办 入驻shopee没身份证怎么办 液相色谱柱柱压降低怎么办 c18色谱柱堵了怎么办 色谱柱进空气了怎么办 宫颈评分只有3分怎么办 淘宝鞋子售后退货商家拒收怎么办 退货申通cp原因怎么办 运费险赔的少怎么办 淘宝卖游戏账号恶意退款怎么办 淘宝账号体检虚拟违规怎么办 京东虚拟单被骗怎么办 网络公选课挂科怎么办 淘宝评论被商家关闭怎么办? 皇冠车钥匙丢了怎么办 皇冠行李箱钥匙丢了怎么办 淘宝主推产品扣两分怎么办 淘宝直通车宝贝排查下架怎么办 滴滴车龄超过8年怎么办 购物车超120了怎么办 没发货申请退款卖家不处理怎么办 淘宝卖家帐号被骗了怎么办 淘宝网下单忘了用返利网怎么办 该地域无法观看此直播怎么办 宝宝喝了有活虫的奶粉怎么办 淘宝商家店铺状态异常怎么办 淘宝购物提示买家信息错误怎么办 苹果淘宝占用空间大怎么办 苹果手机淘宝占内存太大怎么办 苹果手机淘宝图标找不到了怎么办 苹果手机看淘宝很卡怎么办 苹果手机淘宝忘了密码怎么办 苹果手机更新后淘宝打不开怎么办