转载至:http://blog.csdn.net/liuhongwei123888/article/details/51180116
上一章已经介绍了Retrofit创建过程,这章介绍Retrofit Api Service创建与访问过程。
Retrofit 相比Volley等网络框架一个最大区别就是它只需要声明接口,就可以访问网络,刚刚使用的时候觉得很神奇,有木有。
要彻底理解底层实现访问,需要先来看看Java的动态代理。
public interface Subject { boolean login(String username, String password); }
/** * 真实对象 * @author Micky Liu * */ public class RealSubject implements Subject { @Override public boolean login(String username, String password) { System.out.println("username = " + username + ", passwd = " + password); return "MickyLiu".equals(username) && "123456".equals(password); } }
/** * 动态代理类 * @author Micky Liu * */ public class DynamicProxy implements InvocationHandler { /**需要代理的真实对象*/ private Object subject; public DynamicProxy(Object subject) { this.subject = subject; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before invoke subject method \"" + method + "\""); boolean b = (boolean) method.invoke(subject, args); System.out.println("After invoked subject method \"" + method + "\"") ; return b; } }
public class ProxySample { public static void main(String[] args) { //真实对象 Subject realSubject = new RealSubject(); //代理对象 InvocationHandler handler = new DynamicProxy(realSubject); //Proxy.newProxyInstance有三个参数 //参数1:代理类加载器 //参数2:真实对象实现的接口,这里用于关联代理对象和真实对象,确保代理对象里调用的方法是和真实对象同名的方法 //参数3:代理对象 Subject subject = (Subject) Proxy.newProxyInstance(handler.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler); boolean isSuccess = subject.login("MickyLiu", "123456"); String result = isSuccess ? "login success" : "login failed"; System.out.println(result); } }Retrofit除了使用上述的动态代理,还使用了Annotation即注解。在Retrofit中使用了自定义注解,如@POST @GET @Path @Query等,就像我们在接口中定义的:
@POST(Constants.URL_UPDATE_USER_LIST) Observable<BaseResponse<List<User>>> updateUserList(@Query("userList") String userList);
看看我们前面使用过的代码:
Retrofit retrofit = new Retrofit.Builder() .baseUrl(getEndPoint(t)) .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .client(clientBuilder.build()) .build(); service = retrofit.create(t);
这章的重点 retrofit.create方法,它用来创建API Service接口,返回的对象是我们定义的Service,有了它我们就能直接调用service.updateUserList来访问网络接口了。来查看下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, 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 serviceMethod = loadServiceMethod(method); OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args); return serviceMethod.callAdapter.adapt(okHttpCall); } }); }
首先调用validateServiceInterface只是调用了service.isInterface()方法判断是否这个对象是一个接口对象,不要问我isInterface()方法哪里来的,去jdk的Class类里找。
往下是不是看见了前面介绍的动态代理?好吧,我明白了,Retrofit 不就是简单的使用动态代理,就实现了所谓只要声明接口就能访问网络了么。简单么?
到这里我们已经知道retrofit 内部是怎么创建的了,接下来就看看它是怎么完成访问流程的。
method.getDeclaringClass() == Object.class //这段代码用来判断当前方法是否是声明在Object中的访问
platform.isDefaultMethod(method) //这段代码用来判断是否是默认代码,当Platform是Android的时候永远返回是false
接下来的代码才是我们的重点了
ServiceMethod loadServiceMethod(Method method) { ServiceMethod result; synchronized (serviceMethodCache) { result = serviceMethodCache.get(method); if (result == null) { result = new ServiceMethod.Builder(this, method).build(); serviceMethodCache.put(method, result); } } return result; }
看看ServiceMethodCache的定义,键:method对象, 值ServiceMethod对象,如果已经Map中缓存了这个method则直接取,没有则创建一个ServiceMethod存到map中并将这个serviceMethod返回。
private final Map<Method, ServiceMethod> serviceMethodCache = new LinkedHashMap<>();
public Builder(Retrofit retrofit, Method method) { this.retrofit = retrofit; this.method = method; this.methodAnnotations = method.getAnnotations(); this.parameterTypes = method.getGenericParameterTypes(); this.parameterAnnotationsArray = method.getParameterAnnotations(); }
methodAnnotations是方法注解即POST(url),实际取到的值:@retrofit2.http.POST(value=UpdateUserList)]
parameterTypes 是参数类型的数组,实际取到的值:[class java.lang.String]
parameterAnnotationsArray 是参数注解即@Query(“userList”),实际取到的值:[@retrofit2.http.Query(encoded=false, value=userList)]
ServiceMethod.Builder.build()方法:
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); }返回的callAdapter为我们配置的“class retrofit2.adapter.rxjava.RxJavaCallAdapterFactory$SimpleCallAdapter”
responseConverter为我们配置的“class retrofit2.converter.gson.GsonResponseBodyConverter”
parseMethodAnnotation用于将我们接口的method注解解析出来,保存在ServiceMethod.Builder类的成员变量里,以供后续使用。
接着的代码是通过获取参数注解解析我们的参数列表。
private CallAdapter<?> createCallAdapter() { Type returnType = method.getGenericReturnType(); if (Utils.hasUnresolvableType(returnType)) { throw methodError( "Method return type must not include a type variable or wildcard: %s", returnType); } if (returnType == void.class) { throw methodError("Service methods cannot return void."); } Annotation[] annotations = method.getAnnotations(); try { return retrofit.callAdapter(returnType, annotations); } catch (RuntimeException e) { // Wide exception range because factories are user code. throw methodError(e, "Unable to create call adapter for %s", returnType); } }此处可以获取到returnType为rx.Observable<com.micky.retrofitsample.netservice.response.BaseResponse<java.util.List<com.micky.retrofitsample.model.User>>>,这不就是我们定义的接口返回类型么。
-
顶