资料

Android:手把手带你 深入读懂 Retrofit 2.0 源码Retrofit源码解析从动态代理角度看Retrofit,这才是Retrofit的精髓!
square/retrofitandroid_retrofit的使用(GET)
Retrofit2源码分析:架构全面解析
Retrofit2【Android】Retrofit网络请求参数注解,@Path、@Query、@QueryMap…
Retrofit源码解析从动态代理角度看Retrofit,这才是Retrofit的精髓!
square/retrofitandroid_retrofit的使用(GET)
Retrofit基本使用和源码解析 https://github.com/guiying712/AndroidModulePattern使用Retrofit2封装适用于组件化项目的网络库

用法

public interface GetRequest_Interface {

    @GET("openapi.do?keyfrom=abc&key=2032414398&type=data&doctype=json&version=1.1&q=car")
    Call<Reception> getCall(@Field("name") String name);
    // @GET注解的作用:采用Get方法发送网络请求
 
    // getCall() = 接收网络请求数据的方法
    // 其中返回类型为Call<*>,*是接收数据的类(即上面定义的Translation类)
    // 如果想直接获得Responsebody中的内容,可以定义网络请求返回值为Call<ResponseBody>
}


public interface GetRequest_Interface {
    /**
     * method:网络请求的方法(区分大小写)
     * path:网络请求地址路径
     * hasBody:是否有请求体
     */
    @HTTP(method = "GET", path = "blog/{id}", hasBody = false)
    Call<ResponseBody> getCall(@Path("id") int id);
    // {id} 表示是一个变量
    // method 的值 retrofit 不会做处理,所以要自行保证准确
}


public interface GetRequest_Interface {
        /**
         *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
         * <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);
         
        /**
         * {@link Part} 后面支持三种类型,{@link RequestBody}、{@link okhttp3.MultipartBody.Part} 、任意类型
         * 除 {@link okhttp3.MultipartBody.Part} 以外,其它类型都必须带上表单字段({@link okhttp3.MultipartBody.Part} 中已经包含了表单字段的信息),
         */
        @POST("/form")
        @Multipart
        Call<ResponseBody> testFileUpload1(@Part("name") RequestBody name, @Part("age") RequestBody age, @Part MultipartBody.Part file);

}


// @Header
@GET("user")
Call<User> getUser(@Header("Authorization") String authorization)

// @Headers
@Headers("Authorization: authorization")
@GET("user")
Call<User> getUser()

// 以上的效果是一致的。
// 区别在于使用场景和使用方式
// 1. 使用场景:@Header用于添加不固定的请求头,@Headers用于添加固定的请求头
// 2. 使用方式:@Header作用于方法的参数;@Headers作用于方法


public interface GetRequest_Interface {
        /**
         *表明是一个表单格式的请求(Content-Type:application/x-www-form-urlencoded)
         * <code>Field("username")</code> 表示将后面的 <code>String name</code> 中name的取值作为 username 的值
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded1(@Field("username") String name, @Field("age") int age);

/**
         * Map的key作为表单的键
         */
        @POST("/form")
        @FormUrlEncoded
        Call<ResponseBody> testFormUrlEncoded2(@FieldMap Map<String, Object> map);

}


   @GET("/")    
   Call<String> cate(@Query("cate") String cate);
}
// 其使用方式同 @Field与@FieldMap,这里不作过多描述

public interface GetRequest_Interface {
        @GET("users/{user}/repos")
        Call<ResponseBody>  getBlog(@Path("user") String user );
        // 访问的API是:https://api.github.com/users/{user}/repos
        // 在发起请求时, {user} 会被替换为方法的第一个参数 user(被@Path注解作用)
    }


public interface GetRequest_Interface {

        @GET
        Call<ResponseBody> testUrlAndQuery(@Url String url, @Query("showAll") boolean showAll);
       // 当有URL注解时,@GET传入的URL就可以省略
       // 当GET、POST...HTTP等方法中没有设置Url时,则必须使用 {@link Url}提供

}


@DELETE("bean/delete")
Observable<CompanyBean> daleteBean(@Query("id") String id);

总体流程

Retrofit源码解析_表单

创建Retrofit实例

Retrofit retrofit = new Retrofit.Builder()
      .baseUrl("https://github.com")
      .addConverterFactory(GsonConverterFactory.create())
      .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
      .build();

动态代理生成可以使用的方法

动态代理的使用

动态代理在Retrofit中的使用

MiniRetrofit.java

public class MiniRetrofit {
    String mBaseUrl;
    public MiniRetrofit(String baseUrl) {
        mBaseUrl = baseUrl;
    }

    public <T> T create(final Class<T> service) {
        return (T)Proxy.newProxyInstance(
            service.getClassLoader(),
            newe Class<?>{service},
            new InvocationHandler() {
                @Override
                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    // 如果是equals、toString、hashCode方法则直接调用原来的方法
                    if (method.getDeclaringClass() == Object.class) {
                        return method.invoke(this, args);
                    }
                    Call<?> call = null;
                    // 获取被代理的接口的方法注解
                    Annotation[] annotations = method.getDeclaredAnnotations();
                    for (Annotation annotation : annotations) {
                        // 如果找到对应的Get注解, 则将Get注解中的url和mBaseUrl拼接在一起
                        if (annotation instanceof Get) {
                            String path = ((Get) annotation).value();
                            String url = mBaseUrl + "/" + path;
                            System.out.println("url:"+url);
                            // 通过OkHttp请求url, 并将结果回调到外部
                            final OkHttpClient okHttpClient = new OkHttpClient().newBuilder().build();
                            final Request request = new Request.Builder()
                                .url(url)
                                .build();
                            call = new Call<Object>() {
                                @Override
                                public void enqueue(final CallBack<Object> callBack) {
                                    okHttpClient.newCall(request).enqueue(new Callback(){
                                        @Override
                                        public void onFailure(Call call, IOException e) {
                                            callBack.onFail(e);
                                        }
                                        @Override
                                        public void onResonse(Call call, Response response) {
                                            callBack.onResponse(response.body().string());
                                        }
                                    });
                                }
                            };
                        }
                    }
                }
            }
        );
    }

    static class Builder {
        String baseUrl;
        public Builder baseUrl(String baseUrl) {
            this.baseUrl = baseUrl;
            return this;
        }
        public MiniRetrofit build() {
            return new MiniRetrofit(baseUrl);
        }
    }
}

Proxy.newProxyInstance()总结:

  1. 第一个参数是:ClassLoader, 第二个参数是:Class<?>[](数组),第三个参数:InvocationHandler回调类
  2. loadService调用需要的方法,并保存在集合中

ServiceMethod.parseAnnotations(Retrofit, Method)

static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
  	// 获取注解中的参数
    RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

    Type returnType = method.getGenericReturnType();
    if (Utils.hasUnresolvableType(returnType)) {
      throw methodError(
          method,
          "Method return type must not include a type variable or wildcard: %s",
          returnType);
    }
    if (returnType == void.class) {
      throw methodError(method, "Service methods cannot return void.");
    }
	// 实际要调用的方法
    return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
  }

RequestFactory.parseAnnotations

解析方法上的请求参数(注解上面的参数)

HttpServiceMethod.parseAnnotations

通过反射调用具体的方法,里面使用了代理方法