Retrofit框架原理分析

35 阅读6分钟

一.基本用法

1.创建Retrofit对象
public class HttpRetrofit {
    private static Retrofit mRetrofit;
    public static Retrofit getService(){
        if (mRetrofit == null) {
            synchronized (HttpRetrofit.class) {
                if (mRetrofit == null) {
                    mRetrofit = new Retrofit.Builder()
                            .baseUrl(ApiUrl.BASE_URL)
                            .client(WBHttpClient.getHttpClient())
                            .addConverterFactory(GsonConverterFactory.create())
                            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                            .build();
                }
            }
        }
        return mRetrofit;
    }
}
2.retrofit各种网络请求的用法
  /************************************GET网络请求方式******************************************************/
    //作用:GET请求最简单的写法,无Path参数和Query参数 */
    // @GET("article/list/latest?page=1") Call<ResponseBody> getLatestString();
    //作用:GET请求,指定Path参数和Query参数
    //@GET("article/list/{type}?") Call<QiushiModel> getInfoList(@Path("type") String type, @Query("page") int page);
    //作用:GET请求提交数据
    // @GET("MyWeb/RegServlet") Call<ResponseBody> getRegInfo(@QueryMap Map<String, String> map);
    //作用:GET请求,指定URL参数
    //@GET Call<QiushiModel> getInfoList(@Url String urlString);
    //访问网络,下载大文件。 * 默认情况下,Retrofit在处理结果前会将服务器端的Response全部读进内存
    //@Streaming @GET Call<ResponseBody> getNetworkDataAsync(@Url String urlString);
    /************************************POST网络请求方式******************************************************/
    //作用:post网络请求,向服务器提交表单域数据
    //@FormUrlEncoded @POST("MyWeb/RegServlet") Call<ResponseBody> postFormFields(@Field("username") String username, @Field("password") String password, @Field("age") String age);
    // @FormUrlEncoded @POST("MyWeb/RegServlet") Call<ResponseBody> postFormFieldMap(@FieldMap Map<String , String> map);
    //作用:POST网络请求,上传单个文件,上传后的文件名称已经被指定
    //@Multipart @POST("MyWeb/UploadServlet") Call<ResponseBody> postUploadFile(@Part("uploadfile\";filename=\"myuploadimg.png") RequestBody requestBody);
    //作用:POST网络请求,上传多个文件,同时上传表单域数据
    // @POST("MyWeb/UPloadServlet") Call<ResponseBody> postUploadFilesMultipartBody(@Body MultipartBody multipartBody);}
//和Rxjava一起连用
  @GET(ApiUrl.GET_MARKET)
    Observable<BaseResult<List<MarketBean>>> getMarket(@QueryMap Map<String ,Object> map);

 mRetrofit.create(WebService.class).getMarket(map).
                subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).
                subscribe(new ObserverCallBack<BaseResult<List<MarketBean>>>(new ApiCallBack<BaseResult<List<MarketBean>>>() {
                    @Override
                    public void onSuccess(BaseResult<List<MarketBean>> baseResult) {

                    }
                    @Override
                    public void onFailture(Throwable e,int errorCode) {

                    }
                }));
3.动态代理示例【www.cnblogs.com/gonjan-blog…

image.png

动态代理(代理类在运行前不存在,运行时由程序生成的代理方式叫动态代理) 实现方式:创建一个实现了InvocationHandler 接口的类,然后实现其invoke方法,然后使用Proxy.newProxyInstance()方法创建代理对象,通过代理对象,调用接口中的方法,实际上是调用的InvocationHandler 中的invoke方法

/**
 * 创建Person接口
 * @author Gonjan
 */
public interface Person {
    //上交班费
    void giveMoney();
}

public class Student implements Person {
    private String name;
    public Student(String name) {
        this.name = name;
    }
    
    @Override
    public void giveMoney() {
        try {
          //假设数钱花了一秒时间
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
       System.out.println(name + "上交班费50元");
    }
}

public class StuInvocationHandler<T> implements InvocationHandler {
   //invocationHandler持有的被代理对象
    T target;
    
    public StuInvocationHandler(T target) {
       this.target = target;
    }
    
    /**
     * proxy:代表动态代理对象
     * method:代表正在执行的方法
     * args:代表调用目标方法时传入的实参
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理执行" +method.getName() + "方法");
     */   
        //代理过程中插入监测方法,计算该方法耗时
        MonitorUtil.start();
        Object result = method.invoke(target, args);
        MonitorUtil.finish(method.getName());
        return result;
    }
}

测试代理类:


public class ProxyTest {
    public static void main(String[] args) {
        
        //创建一个实例对象,这个对象是被代理的对象
        Person zhangsan = new Student("张三");
        
        //创建一个与代理对象相关联的InvocationHandler
        InvocationHandler stuHandler = new StuInvocationHandler<Person>(zhangsan);
        
        //创建一个代理对象stuProxy来代理zhangsan,代理对象的每个执行方法都会替换执行Invocation中的invoke方法
        Person stuProxy = (Person) Proxy.newProxyInstance(Person.class.getClassLoader(), new Class<?>[]{Person.class}, stuHandler);

       //代理执行上交班费的方法
        stuProxy.giveMoney();
    }
}

打印结果: image.png

二.原理解析

(1)通过构造者模式创建一个retrofit实例,配置baseUrl,OkHttpClient,CallAdapterFactory(Rxjava2CallAdapterFactory将代理返回的call对象转化为Observable对象), ConvertFactory(GsonConvertFactory将代理返回的请求的结果转化为javabean)

(2).通过retrofit对象的create(Class service)返回一个Service的动态代理对象,在调用Service的方法的时候,就是动态调用invoke方法,在Invoke方法中,调用loadServiceMethod(method),在这个方法中会通过给method进行反射,解析注解,得到参数,请求头,请求地址,等等,构建Request请求所有需要的参数等,并提供toRequest()方法得到Request实例,然后构建OkHttpCall(servicMethod,args),通过 serviceMethod.callAdapter.adat(okHttpCall),返回一个Observable或者是Call。

如果是Call<T> call;
call.enqueue( Callback<T> callback){
    Request request = serviceMethod.toRequest(args);
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
}
如果是Observable<T> ,会调用subcribe添加观察者,实际会调用subscribeActual(),在此方法中
observable.subcribe(new Observer(){}) //添加观察者
 //Observable接口中的订阅方法
  public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
            observer = RxJavaPlugins.onSubscribe(this, observer);
            ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
            subscribeActual(observer); //调用该方法
        } catch (NullPointerException e) { // NOPMD
            throw e;
        } catch (Throwable e) {  
        }
    }
//CallEnqueueObservable中
 protected void subscribeActual(Observer<? super Response<T>> observer) {
    // Since Call is a one-shot type, clone it for each new observer.
    Call<T> call = originalCall.clone();
    CallCallback<T> callback = new CallCallback<>(call, observer);
    observer.onSubscribe(callback);
    call.enqueue(callback);//执行OKHttpCall中的enqueue方法
  }

(3).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);
            /*   adapt方法中根据addCallAdapterFactory类型,如果是RxJava2CallAdapterFactory就返回 
                  Observable<T>, 如果不传,则返回Call<T>   */
              return serviceMethod.callAdapter.adapt(okHttpCall); 
          }
        });
  }

//Retrofit中构造模式创建一个ServiceMethod对象
  ServiceMethod<?, ?> loadServiceMethod(Method method) {
    ServiceMethod<?, ?> result = serviceMethodCache.get(method);
    if (result != null) return result;
    synchronized (serviceMethodCache) {
      result = serviceMethodCache.get(method);
      if (result == null) {
 // this表示Retrofit,retrofit里面持有baseUrl,okHttpClient,convertFactory,callAdapterFactory
//method通过反射,解析注解,得到参数,header,isMulpart,isbody,isFormUrlEncode等构建Request的
//必要参数,并提供toRequest()返回Reqeust对象.
        result = new ServiceMethod.Builder<>(this, method).build();
        serviceMethodCache.put(method, result);
      }
    }
    return result;
  }

  public ServiceMethod build() {
      callAdapter = createCallAdapter();
      responseType = callAdapter.responseType();
      if (responseType == Response.class || responseType == okhttp3.Response.class) {
        throw methodError("'"
            + Utils.getRawType(responseType).getName()
            + "' is not a valid response body type. Did you mean ResponseBody?");
      }
      responseConverter = createResponseConverter();

      for (Annotation annotation : methodAnnotations) {
        parseMethodAnnotation(annotation); //
      }

      if (httpMethod == null) {
        throw methodError("HTTP method annotation is required (e.g., @GET, @POST, etc.).");
      }

      if (!hasBody) {
        if (isMultipart) {
          throw methodError(
              "Multipart can only be specified on HTTP methods with request body (e.g., @POST).");
        }
        if (isFormEncoded) {
          throw methodError("FormUrlEncoded can only be specified on HTTP methods with "
              + "request body (e.g., @POST).");
        }
      }

      int parameterCount = parameterAnnotationsArray.length;
      parameterHandlers = new ParameterHandler<?>[parameterCount];
      for (int p = 0; p < parameterCount; p++) {
        Type parameterType = parameterTypes[p];
        if (Utils.hasUnresolvableType(parameterType)) {
          throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
              parameterType);
        }

        Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
        if (parameterAnnotations == null) {
          throw parameterError(p, "No Retrofit annotation found.");
        }

        parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
      }

      if (relativeUrl == null && !gotUrl) {
        throw methodError("Missing either @%s URL or @Url parameter.", httpMethod);
      }
      if (!isFormEncoded && !isMultipart && !hasBody && gotBody) {
        throw methodError("Non-body HTTP method cannot contain @Body.");
      }
      if (isFormEncoded && !gotField) {
        throw methodError("Form-encoded method must contain at least one @Field.");
      }
      if (isMultipart && !gotPart) {
        throw methodError("Multipart method must contain at least one @Part.");
      }

      return new ServiceMethod<>(this);
    }
 /*解析注解得到构建RequestBuilder的核心参数httpMethod,baseUrl,relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart */

 private void parseMethodAnnotation(Annotation annotation) {
      if (annotation instanceof DELETE) {
        parseHttpMethodAndPath("DELETE", ((DELETE) annotation).value(), false);
      } else if (annotation instanceof GET) {
        parseHttpMethodAndPath("GET", ((GET) annotation).value(), false);
      } else if (annotation instanceof HEAD) {
        parseHttpMethodAndPath("HEAD", ((HEAD) annotation).value(), false);
        if (!Void.class.equals(responseType)) {
          throw methodError("HEAD method must use Void as response type.");
        }
      } else if (annotation instanceof PATCH) {
        parseHttpMethodAndPath("PATCH", ((PATCH) annotation).value(), true);
      } else if (annotation instanceof POST) {
        parseHttpMethodAndPath("POST", ((POST) annotation).value(), true);
      } else if (annotation instanceof PUT) {
        parseHttpMethodAndPath("PUT", ((PUT) annotation).value(), true);
      } else if (annotation instanceof OPTIONS) {
        parseHttpMethodAndPath("OPTIONS", ((OPTIONS) annotation).value(), false);
      } else if (annotation instanceof HTTP) {
        HTTP http = (HTTP) annotation;
        parseHttpMethodAndPath(http.method(), http.path(), http.hasBody());
      } else if (annotation instanceof retrofit2.http.Headers) {
        String[] headersToParse = ((retrofit2.http.Headers) annotation).value();
        if (headersToParse.length == 0) {
          throw methodError("@Headers annotation is empty.");
        }
        headers = parseHeaders(headersToParse);
      } else if (annotation instanceof Multipart) {
        if (isFormEncoded) {
          throw methodError("Only one encoding annotation is allowed.");
        }
        isMultipart = true;
      } else if (annotation instanceof FormUrlEncoded) {
        if (isMultipart) {
          throw methodError("Only one encoding annotation is allowed.");
        }
        isFormEncoded = true;
      }
    }

(4).ServiceMethod中提供toRequest()生成Request.

 Request toRequest(@Nullable Object... args) throws IOException {
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);

    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    int argumentCount = args != null ? args.length : 0;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }

    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }

    return requestBuilder.build();
  }

(5).当我们获取到一个Observable,是如何触发OkHttpCall执行的呢?

 //Observable接口中的订阅方法
  public final void subscribe(Observer<? super T> observer) {
        ObjectHelper.requireNonNull(observer, "observer is null");
        try {
            observer = RxJavaPlugins.onSubscribe(this, observer);
            ObjectHelper.requireNonNull(observer, "Plugin returned null Observer");
            subscribeActual(observer); //调用该方法
        } catch (NullPointerException e) { // NOPMD
            throw e;
        } catch (Throwable e) {  
        }
    }
//CallEnqueueObservable中
 protected void subscribeActual(Observer<? super Response<T>> observer) {
    // Since Call is a one-shot type, clone it for each new observer.
    Call<T> call = originalCall.clone();
    CallCallback<T> callback = new CallCallback<>(call, observer);
    observer.onSubscribe(callback);
    call.enqueue(callback);//执行OKHttpCall中的enqueue方法
  }

 public void enqueue(final Callback<T> callback) {
        okhttp3.Call call;
     Request request = serviceMethod.toRequest(args);
    //执行Request请求.
    okhttp3.Call   call = serviceMethod.callFactory.newCall(request); //callFactory就是OkHttpClient实例
  }