Retrofit2是一个网络框架,基于OkHttp3框架封装的网络框架。
大致理解,实现一个Api对应的接口,调用Retrofit.create 方法,通过动态代理模式生成对应的代理service,并加入okhttp的请求队列中,之后可以调用对应的方法进行请求。
创建service的方式:如果想调用同步的请求,只需调用execute方法,而enqueue则会调用一个异步请求。
优点:1.降低耦合度,api之间互不干扰 2.代码风格:使用注解方式,代码简洁(相同的还有ButterKnife,以及degger,EventBus等框架同样是使用注解) 3.采用构建者模式以及动态代理模式,更灵活
Retrofit2使用流程
1初始化Retrofit(构建者模式)
Retrofit singleton;
//拦截 用于输出LOG 将请求以及返回值以log形式打印出来
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Log.i("tag", "log: ========" + message);
}
}).setLevel(HttpLoggingInterceptor.Level.BODY);
HttpLoggingInterceptor interceptor =new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Log.i("tag", "log: ========" + message);
}
}).setLevel(HttpLoggingInterceptor.Level.BODY);
//将拦截器add给OkhttpClient 在不设置OkHttpclient的情况下 retrofit会使用默认的client
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.writeTimeout(10, TimeUnit.SECONDS)
.addInterceptor(interceptor)
.build();
singleton = new Retrofit.Builder()
.baseUrl(host)
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())//支持rxandroid使用的 需要依赖另外的框架
.addConverterFactory(GsonConverterFactory.create())
//支持gson解析使用的 需要依赖另外的框架 compile 'com.squareup.retrofit2:converter-gson:2.2.0'
.client(okHttpClient)
.build();
2.创建对应的api接口
二:部分源码解析public interface NewsApiService {}/** * 参数过多 */ @GET("users/stven0king/repos") Call<String> getNewsByMap(@QueryMap Map<String, String> params);详细的注解使用方式 http://blog.csdn.net/xiangjai/article/details/51452217
http://www.open-open.com/lib/view/open1453552147323.html
3.api进行请求
NewsApiService newsApiService = retrofit.create(NewsApiService.class);
Map<String,String> map=new HashMap<>(); map.put("a","a"); //get 参数map Call<String> newsByMap = newsApiService.getNewsByMap(map); newsByMap.enqueue(new Callback<String>() { @Override public void onResponse(Call<String> call, Response<String> response) { } @Override public void onFailure(Call<String> call, Throwable t) { } });
每次生成的api对应的call只能使用一次,支持取消等方法 如果想调用同步的请求,只需调用execute方法,而enqueue则会调用一个异步请求
1.动态代理模式 动态生成对应的代理类,更灵活简便(反射的原理) 并且可以在执行委托类方法时,统一增加另外的处理代码
public interface TestInterface {
void get();
void post();
}
public class CustomHandler implements InvocationHandler{
private TestInterface obj;
public CustomHandler(TestInterface obj) {
this.obj = obj;
}
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
Log.d("tag", "invoke() called with: o = [" + o + "], method = [" + method + "], objects = [" + objects + "]");
return method.invoke(this.obj,objects);
}
}
TestInterface realSub=new RealSub(); CustomHandler handler=new CustomHandler(realSub); TestInterface proxyInstance = (TestInterface) Proxy.newProxyInstance(realSub.getClass().getClassLoader(), realSub.getClass().getInterfaces(), handler); proxyInstance.get(); proxyInstance.post();
Retrofit2中的源码
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, 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); }//从缓存中取出调用的方法,并生成对应的okhttp的请求,调用请求方法的时候,返回请求结果 ServiceMethod<Object, Object> serviceMethod = (ServiceMethod<Object, Object>) loadServiceMethod(method); OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall);} }); }
private void eagerlyValidateMethods(Class<?> service) { Platform platform = Platform.get(); for (Method method : service.getDeclaredMethods()) { if (!platform.isDefaultMethod(method)) { loadServiceMethod(method); } } } //将加载的类中的方法加入map的缓存中。 ServiceMethod<?, ?> loadServiceMethod(Method method) { ServiceMethod<?, ?> result = serviceMethodCache.get(method); if (result != null) return result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = new ServiceMethod.Builder<>(this, method).build(); serviceMethodCache.put(method, result); } } return result; }