zoukankan      html  css  js  c++  java
  • Retrofit简要分析


    Retrofit是对网络请求实现了一套请求架构封装,屏蔽底层网络实现,使网络请求像调用本地接口一样

    基本使用例子

    public interface GitHubService {//定义request方法以及返回需要的response类型
    		  @GET("users/{user}/repos")
    		  List<Repo> listRepos(@Path("user") String user);
    		  @GET("users/{user}/repos")
    		  Call<List<Repo>> listRepos2(@Path("user") String user,Callback<List<Repo>> calback);
    	}
    	
    void usetest(){
    		static final String BASE_URL = "http://yourwebsite/services/";
                    Retrofit retrofit = new Retrofit.Builder()
                            .baseUrl(BASE_URL) 
                .addConverterFactory(GsonConverterFactory.create())//Response转换器,这里以GsonConvert为例
                 .addCallAdapterFactory(Java8CallAdapterFactory.create())//request处理Adapter .build(); GitHubService service = retrofit.create(GitHubService.class); // 直接调用 List<Repo> data = service.listRepos("user1"); // 异步callback方式 service.listRepos2("user2",new Callback<List<Repo>>() { @Override public void onResponse(Call<List<Repo>> call, Response<List<Repo>> response) { data=response.body(); } @Override public void onFailure(Call<List<Repo>> call, Throwable t) { Log.e("error",t.getMessage()); } }); }

      

    调用流程

    分析调用实现:首先从create开始

     public <T> T create(final Class<T> service) {
        Utils.validateServiceInterface(service);//校验service接口定义是否合法
        if (validateEagerly) {
          eagerlyValidateMethods(service);
        }
        return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },//产生代理,实现对service接口调用
            new InvocationHandler() {
              private final Platform platform = Platform.get();
    
              @Override public Object invoke(Object proxy, Method method, Object... args)
                  throws Throwable {
                ...
             //每个接口最终转换为ServiceMethod,存储在serviceMethodCache中
              ServiceMethod<Object, Object> serviceMethod =
                    (ServiceMethod<Object, Object>) loadServiceMethod(method);
             //网络访问与okhttp结合生成OkHttpCall
               OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            //发起请求,返回结果,解析返回
               return serviceMethod.callAdapter.adapt(okHttpCall);
              }
            });
      }
    

      

    这里的OkHttpCall是Retrofit对自身Call接口实现,并不是okhttp3里的对象,通过实现接口内部封装okhttp3.Call,当然也可以替换其它网络库

    看看call接口

    public interface Call<T> extends Cloneable {
      ...
      Response<T> execute() throws IOException;
    ...
      void enqueue(Callback<T> callback);
    ...
      boolean isExecuted();
    ...
      void cancel();
    
      /** The original HTTP request. */
      Request request();
    }
    

    与okhttp里面call类似,只不过自身重新定义一下,降低耦合度

    看看Okhttp3实现类

    final class OkHttpCall<T> implements Call<T> {
      private final ServiceMethod<T, ?> serviceMethod;
      private final Object[] args;
    
      private volatile boolean canceled;
    
      // All guarded by this.
      private okhttp3.Call rawCall;
      private Throwable creationFailure; // Either a RuntimeException or IOException.
      private boolean executed;
    
      OkHttpCall(ServiceMethod<T, ?> serviceMethod, Object[] args) {
        this.serviceMethod = serviceMethod;
        this.args = args;
      }
    ......
      @Override public void enqueue(final Callback<T> callback) {//异步请求
        if (callback == null) throw new NullPointerException("callback == null");
    
        okhttp3.Call call;
        Throwable failure;
    
        synchronized (this) {
          if (executed) throw new IllegalStateException("Already executed.");
          executed = true;
    ...
        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);//解析response
            } catch (Throwable e) {
              callFailure(e);
              return;
            }
            callSuccess(response);
          }
    
         ......
        });
      }
    
      @Override public Response<T> execute() throws IOException {//同步调用请求
        okhttp3.Call call;
    
        synchronized (this) {
          if (executed) throw new IllegalStateException("Already executed.");
          executed = true;
    ......
          call = rawCall;
          if (call == null) {
            try {
              call = rawCall = createRawCall();
            } catch (IOException | RuntimeException e) {
              creationFailure = e;
              throw e;
            }
          }
        }
    
        if (canceled) {
          call.cancel();
        }
    
        return parseResponse(call.execute());//执行请求并解析
      }
    
      private okhttp3.Call createRawCall() throws IOException {
        Request request = serviceMethod.toRequest(args);
        okhttp3.Call call = serviceMethod.callFactory.newCall(request);
        if (call == null) {
          throw new NullPointerException("Call.Factory returned null.");
        }
        return call;
      }
    
      Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
        ResponseBody rawBody = rawResponse.body();
    
        // Remove the body's source (the only stateful object) so we can pass the response along.
        rawResponse = rawResponse.newBuilder()
            .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
            .build();
    
        ......
    
        ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
        try {
          T body = serviceMethod.toResponse(catchingBody);//调用指定的Convert对response进行泛型转换
          return Response.success(body, rawResponse);
        } catch (RuntimeException e) {
          // If the underlying source threw an exception, propagate that rather than indicating it was
          // a runtime exception.
          catchingBody.throwIfCaught();
          throw e;
        }
      }
    

      

    convert最终调用来源Retrofit里的在builder里加入Converter.Factory

    public <T> Converter<ResponseBody, T> nextResponseBodyConverter(Converter.Factory skipPast,
          Type type, Annotation[] annotations) {
        checkNotNull(type, "type == null");
        checkNotNull(annotations, "annotations == null");
    
        int start = converterFactories.indexOf(skipPast) + 1;
        for (int i = start, count = converterFactories.size(); i < count; i++) {
          Converter<ResponseBody, ?> converter =
              converterFactories.get(i).responseBodyConverter(type, annotations, this);
          if (converter != null) {
            //noinspection unchecked
            return (Converter<ResponseBody, T>) converter;
          }
        }
    
    
     public Builder addConverterFactory(Converter.Factory factory) {
          converterFactories.add(checkNotNull(factory, "factory == null"));
          return this;
        }
    

      

    看看GsonResponseBodyConverter实现

    final class GsonResponseBodyConverter<T> implements Converter<ResponseBody, T> {
      private final Gson gson;
      private final TypeAdapter<T> adapter;
    
      GsonResponseBodyConverter(Gson gson, TypeAdapter<T> adapter) {
        this.gson = gson;
        this.adapter = adapter;
      }
    
      @Override public T convert(ResponseBody value) throws IOException {//通过TypeAdapter转换为对应实体类型T
        JsonReader jsonReader = gson.newJsonReader(value.charStream());
        try {
          return adapter.read(jsonReader);
        } finally {
          value.close();
        }
      }
    }
    

      


    整理一下,Retrofit使用Jdk里的Proxy动态代理方式实现对接口方法调用,即当调用接口方法listRepos时,调用了Proxy中的invoke,将对应接口方法及注解封装为ServiceMethod对象,通过CallAdapter对OkHttpCall调用获取Response并将数据转换为T返回给调用者

    Retrofit中build构建方法:

    public Retrofit build() {
          if (baseUrl == null) {
            throw new IllegalStateException("Base URL required.");
          }
    
          okhttp3.Call.Factory callFactory = this.callFactory;
          if (callFactory == null) {//检测网络请求client,如果没有指定则创建一个client
            callFactory = new OkHttpClient();
          }
    
          Executor callbackExecutor = this.callbackExecutor;
          if (callbackExecutor == null) {//回调执行callback的线程,如果没有指定则采用默认主线程
            callbackExecutor = platform.defaultCallbackExecutor();
          }
    
          //CallAdapter指的是对request处理的CallAdapter,可以添加多个
          List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
          adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
    
          // Converter是对response执行转换处理返回的T,可以添加多个
          List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
    
          return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
              callbackExecutor, validateEagerly);
        }
    
    
    

      

    CallAdapter接口定义

    public interface CallAdapter<R, T> {
      //http 解析response 返回类型,不是咱接口定义泛型
      Type responseType();
    
      //处理response并转换为指定类型T
      T adapt(Call<R> call);
    
      //CallAdapter 创建获取
      abstract class Factory {
        /**
         * Returns a call adapter for interface methods that return {@code returnType}, or null if it
         * cannot be handled by this factory.
    	 *根据接口返回类型,注解类型判断当前CallAdapter是否支持,不支持返回为null
         */
        public abstract CallAdapter<?, ?> get(Type returnType, Annotation[] annotations,
            Retrofit retrofit);
    
        /**
         * Extract the upper bound of the generic parameter at {@code index} from {@code type}. For
         * example, index 1 of {@code Map<String, ? extends Runnable>} returns {@code Runnable}.
    	 *获取指定index泛型参数上限,例如Map<String, ? extends Runnable> index为1参数上限为Runnable
         */
        protected static Type getParameterUpperBound(int index, ParameterizedType type) {
          return Utils.getParameterUpperBound(index, type);
        }
    
        /**
         * Extract the raw class type from {@code type}. For example, the type representing
         * {@code List<? extends Runnable>} returns {@code List.class}.
         */
    	 //获取解析类型class,例如List<? extends Runnable>,返回List.class
        protected static Class<?> getRawType(Type type) {
          return Utils.getRawType(type);
        }
      }
    

      

    项目中有三种实现

    RxJava Observable & Single - com.squareup.retrofit2:adapter-rxjava
    Guava ListenableFuture - com.squareup.retrofit2:adapter-guava
    Java 8 CompleteableFuture - com.squareup.retrofit2:adapter-java8

    看一下java8实现

    Java8CallAdapterFactory

    private static final class BodyCallAdapter<R> implements CallAdapter<R, CompletableFuture<R>> {
        private final Type responseType;
    
        BodyCallAdapter(Type responseType) {
          this.responseType = responseType;
        }
    
        @Override public Type responseType() {
          return responseType;
        }
    
        @Override public CompletableFuture<R> adapt(final Call<R> call) {
          final CompletableFuture<R> future = new CompletableFuture<R>() {
            @Override public boolean cancel(boolean mayInterruptIfRunning) {
              if (mayInterruptIfRunning) {
                call.cancel();
              }
              return super.cancel(mayInterruptIfRunning);
            }
          };
    
          call.enqueue(new Callback<R>() {//调用okhttp Call方法异步调用
            @Override public void onResponse(Call<R> call, Response<R> response) {
              if (response.isSuccessful()) {
                future.complete(response.body());
              } else {
                future.completeExceptionally(new HttpException(response));
              }
            }
    
            @Override public void onFailure(Call<R> call, Throwable t) {
              future.completeExceptionally(t);
            }
          });
    
          return future;
        }
      }
    

      

    到这里我们已取到数据结果,再看看转换如何实现ServiceMethod的toResponse

    /** Builds a method return value from an HTTP response body. */
      R toResponse(ResponseBody body) throws IOException {
        return responseConverter.convert(body);
      }
    

    通过serviceMethod 中的Converter<ResponseBody, R> responseConverter;实现进行解析

    Converter为转换接口,实现类有以下

      Gson - com.squareup.retrofit2:converter-gson
        Jackson - com.squareup.retrofit2:converter-jackson
        Moshi - com.squareup.retrofit2:converter-moshi
        Protobuf - com.squareup.retrofit2:converter-protobuf
        Wire - com.squareup.retrofit2:converter-wire
        Simple Framework - com.squareup.retrofit2:converter-simpleframework
        Scalars - com.squareup.retrofit2:converter-scalars

    当然也可以自定义实现Converter,定制出符合自己需求转换器

    从上面分析看出Retorfit中的3个核心部分:

    1,Proxy     代理实现接口调用

    2,CallAdapters   request网络t处理
    3,Converters    response解析转换对应泛型T返回数据结果


  • 相关阅读:
    Docker简介,安装,配置
    Centos7给 root 账户开通ssh权限
    [转载]Hyper-v 安装CentOS 7
    软件开发_六大原则
    php函数名后冒号(:)+数据类型(返回值类型限制/php新特性)
    MySQL--事务介绍
    MySQL存储引擎
    leetcode刷题笔记300题 最长上升子序列
    leetcode刷题笔记299题 猜数字游戏
    **leetcode刷题笔记四 两个有序序列的中位数**
  • 原文地址:https://www.cnblogs.com/happyxiaoyu02/p/6150734.html
Copyright © 2011-2022 走看看