一键归纳okhttp3+retrofit2架构,反射+注解+retrofit手写框架
下面两篇文章是我觉得理解比较透彻和详细的文章
一、首先你需要了解什么是动态代理
Retrofit源码学习之动态代理
二、其次你要了解一下retrofit2的基本使用以及源码解析
Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装,网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责网络请求接口的封装。
从架构角度看Retrofit的作用、原理和启示
三、简单的利用注解反射实现retrofit网络请求,有助于理解其中的基本原理
此处仅为基本使用,适配器和转换器未使用。距离完整的框架还差一大截
下面开始看代码
元数据
public interface WeatherApi {@POST("/v3/weather/weatherInfo")@FormUrlEncodedCall postWeather(@Field("city") String city, @Field("key") String key);@GET("/v3/weather/weatherInfo")Call getWeather(@Query("city") String city, @Query("key") String key);
}
看一下自定义的注解,用于方法注解,适用于运行期
@Target(METHOD)
@Retention(RUNTIME)
public @interface GET {String value() default "";
}
@Target(METHOD)
@Retention(RUNTIME)
public @interface POST {String value() default "";
}
自定义的retrofit
public class MyRetrofit {final Map serviceMethodCache &#61; new ConcurrentHashMap<>();final Call.Factory callFactory;final HttpUrl baseUrl;MyRetrofit(Call.Factory callFactory, HttpUrl baseUrl) {this.callFactory &#61; callFactory;this.baseUrl &#61; baseUrl;}public T create(final Class service) {return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class[]{service},new InvocationHandler() {&#64;Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//解析这个method 上所有的注解信息ServiceMethod serviceMethod &#61; loadServiceMethod(method);//args:return serviceMethod.invoke(args);}});}private ServiceMethod loadServiceMethod(Method method) {//先不上锁&#xff0c;避免synchronized的性能损失ServiceMethod result &#61; serviceMethodCache.get(method);if (result !&#61; null) return result;//多线程下&#xff0c;避免重复解析,synchronized (serviceMethodCache) {result &#61; serviceMethodCache.get(method);if (result &#61;&#61; null) {result &#61; new ServiceMethod.Builder(this, method).build();serviceMethodCache.put(method, result);}}return result;}/*** 构建者模式&#xff0c;将一个复杂对象的构建和它的表示分离&#xff0c;可以使使用者不必知道内部组成的细节。*/public static final class Builder {private HttpUrl baseUrl;//Okhttp->OkhttClientprivate okhttp3.Call.Factory callFactory; //nullpublic Builder callFactory(okhttp3.Call.Factory factory) {this.callFactory &#61; factory;return this;}public Builder baseUrl(String baseUrl) {this.baseUrl &#61; HttpUrl.get(baseUrl);return this;}public MyRetrofit build() {if (baseUrl &#61;&#61; null) {throw new IllegalStateException("Base URL required.");}okhttp3.Call.Factory callFactory &#61; this.callFactory;if (callFactory &#61;&#61; null) {callFactory &#61; new OkHttpClient();}return new MyRetrofit(callFactory, baseUrl);}}
}
接下来是ServiceMethod 记录请求类型 参数 完整地址
public class ServiceMethod {private final Call.Factory callFactory;private final String relativeUrl;private final boolean hasBody;private final ParameterHandler[] parameterHandler;private FormBody.Builder formBuild;HttpUrl baseUrl;String httpMethod;HttpUrl.Builder urlBuilder;public ServiceMethod(Builder builder) {//获取代理对象myretrofit的参数&#xff0c;以便封装请求参数baseUrl &#61; builder.enjoyRetrofit.baseUrl;callFactory &#61; builder.enjoyRetrofit.callFactory;httpMethod &#61; builder.httpMethod;relativeUrl &#61; builder.relativeUrl;hasBody &#61; builder.hasBody;parameterHandler &#61; builder.parameterHandler;//如果是有请求体,创建一个okhttp的请求体对象if (hasBody) {formBuild &#61; new FormBody.Builder();}}public Object invoke(Object[] args) {/*** 1 处理请求的地址与参数* 这里也是在invoke里要实现的网络请求*/for (int i &#61; 0; i }
public abstract class ParameterHandler {abstract void apply(ServiceMethod serviceMethod, String value);static class QueryParameterHandler extends ParameterHandler {String key;public QueryParameterHandler(String key) {this.key &#61; key;}//serviceMethod: 回调&#64;Overridevoid apply(ServiceMethod serviceMethod, String value) {serviceMethod.addQueryParameter(key,value);}}static class FiledParameterHandler extends ParameterHandler {String key;public FiledParameterHandler(String key) {this.key &#61; key;}&#64;Overridevoid apply(ServiceMethod serviceMethod, String value) {serviceMethod.addFiledParameter(key,value);}}
}
最后调用、点击事件卸在view里。不展示了
public class MainActivity extends AppCompatActivity {private static final String TAG &#61; "MainActivity";private EnjoyWeatherApi enjoyWeatherApi;&#64;Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);MyRetrofit enjoyRetrofit &#61; new MyRetrofit.Builder().baseUrl("https://restapi.amap.com").build();enjoyWeatherApi &#61; enjoyRetrofit.create(EnjoyWeatherApi.class);}public void enjoyPost(View view) {okhttp3.Call call &#61; enjoyWeatherApi.postWeather("110101", "ae6c53e2186f33bbf240a12d80672d1b");call.enqueue(new okhttp3.Callback() {&#64;Overridepublic void onFailure(okhttp3.Call call, IOException e) {}&#64;Overridepublic void onResponse(okhttp3.Call call, okhttp3.Response response) throws IOException {Log.i(TAG, "onResponse enjoy post: " &#43; response.body().string());response.close();}});}
}