您的位置:首页 > 其它

关于Retrofit2.0源码的学习和理解

2016-12-20 12:21 591 查看
    今年4月初,刚接触到RxJava、Retrofit等框架的时候,当时也是一头楞,因为我以前的项目中都是采用MVP加上Volley请求框架的结构。使用Retrofit开源框架搭建项目这个在网络上已经有很多很好的介绍了,在这里就不去探讨怎么使用。之所以要去写源码的实现,一方面呢是因为最近研读了下,对Retrofit有了一些了解,主要是另一个方面,写一写博客(当写笔记吧),一来理清下思路,二来相当于做个笔记,方便后面复习加深下印象。为了能更加清晰的分析Retrofit源码,我还是单独的写个工程,很简单。好嘞!废话不多说了,开始我们的Retrofit2.0源码理解之路吧!

1.简单配置Retrofit2.0

    在app项目下的build.gradle中添加:

compile 'com.squareup.retrofit2:retrofit:2.0.2'
compile 'com.squareup.retrofit2:converter-gson:2.0.0'


    编写一个实体类:

package com.jianzou.retrofit;

/**
* Created by JianZou on 2016/12/19.
*/

public class UserModel
{
private String id;
private String name;
private String age;

public String getId()
{
return id;
}

public void setId(String id)
{
this.id = id;
}

public String getAge()
{
return age;
}

public void setAge(String age)
{
this.age = age;
}

public String getName()
{
return name;
}

public void setName(String name)
{
this.name = name;
}
}


编写interfice类

package com.jianzou.retrofit;

import java.util.List;

import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;

/**
* Created by JianZou on 2016/12/19.
*/

public interface IRequestInter
{
@GET("Users/{action}")
Call<List<UserModel>> getUsers(@Path("action") String action);
}


最后去构建Retrofit

package com.jianzou.retrofit;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;

import java.util.List;

import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

public class MainActivity extends AppCompatActivity
{

@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//构建Retrofit
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://www.ceshi.demo/api")//URL可以修改成自己请求的公共URL部分
.addConverterFactory(GsonConverterFactory.create())//这里使用Gson来转化返回的数据
.build();
/*
根据Java动态代理,动态的获取到每个接口的方法、参数和注解,再将这些拼接成一个request(ServiceMethod.toRequest()方法);
由OKHttp请求后返回结果,然后将返回的数据通过我们设定的GsonConverterFactory转化成Gson格式的数据;
最后,源码中设置的OkHttpCall将返回并转化成Gson格式的数据回调给UI线程。
*/
IRequestInter request = retrofit.create(IRequestInter.class);

Call<List<UserModel>> call = request.getUsers("buy");

call.enqueue(new Callback<List<UserModel>>()
{
@Override
public void onResponse(Call<List<UserModel>> call, Response<List<UserModel>> response)
{

}

@Override
public void onFailure(Call<List<UserModel>> call, Throwable t)
{

}
}

);

}
}
到这,简单的配置下就完了,再次声明:只是为了读源码而配置的这些,实际不能运行的哈!

2.源码分析

从构建Retrofit看起吧:MainActivity --> build() [ MainActivity中创建Retrofit最后面的build()方法,下文类似 ]

这里是创造者模式创建一个Retrofit,具体的代码是:

/**
* Create the {@link Retrofit} instance using the configured values.
* <p>
* Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
* OkHttpClient} will be created and used.
*/
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}

okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}

Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}

// Make a defensive copy of the adapters and add the default Call adapter.
List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));

// Make a defensive copy of the converters.
List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);

return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}

从上到下看来:(1)对baseUrl做了空判断处理。(2)创建OkHttpClient()对象,这个是可以自己在new Retrofit时添加进来的,如果没有配置,默认使用OkHttpClient。(3)Executor线程执行者:在Builder这个class的构造函数中有this(Platform.get()),Platform这个类通过Java反射,判断了当前的平台,我们直接看findPlatform()中的Android()方法,

static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}

@Override CallAdapter.Factory defaultCallAdapterFactory(Executor callbackExecutor) {
return new ExecutorCallAdapterFactory(callbackExecutor);
}

static class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());

@Override public void execute(Runnable r) {
handler.post(r);
}
}
}
这个类默认new的是MainThreadExecutor对象,然后将这个线程放到主线程的消息队列中。通过ExecutorCallAdapterFactory中get()方法返回了final的ExecutorCallbackCall类,(4)
adapterFactories,这个主要是上面call的集合,不需要关心,(5)converterFactories:这个用来将请求返回的数据进行转化以及请求中注解参数的转化。


接着看 MainActivity -->retrofit.create(IRequestInter.class);点击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 f
4000
rom 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);
}
});
}
这里就是用到了Java的动态代理截获接口的方法,参数名等信息。我们主要的看最后几行有效代码:
(1)创建ServiceMethod:




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;
}
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);
}
在ServiceMethod的build方法中:createCallAdapter()返回的实际上是Retrofit Build()方法中我们add到adapterFactories中的callAdapter,callAdapter.responseType()返回的其实就是我们传进去的UserModel类型,而createResponseConverter得到的是responseConverter对象,因为我们在创建Retrofit的时候加了这么一行addConverterFactory(GsonConverterFactory.create()),所以这里返回的是GsonConverterFactory。代码的下面就是对方法和参数注解进行了解析,这里获得到很多的parameterHandler对象,最终在ServiceMethod的toRequest方法调用中,通过parameterHandler的apply方法构造一个完整的请求。
(2)创建OkHttpCall:




OkHttpCall(ServiceMethod<T> serviceMethod, Object[] args) {
this.serviceMethod = serviceMethod;
this.args = args;
}
这一步主要是把上面创建的serviceMethod以及接口中方法的参数存在本类中。
(3)serviceMethod.callAdapter.adapt(okHttpCall):


这里的callAdapter就是上面serviceMethod.build()中createCallAdapter()返回的,而createCallAdapter最终也是通过ExecutorCallAdapterFactory中get()方法返回ExecutorCallbackCall类:



@Override
public CallAdapter<Call<?>> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Call<?>>() {
@Override public Type responseType() {
return responseType;
}

@Override public <R> Call<R> adapt(Call<R> call) {
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}



static final class ExecutorCallbackCall<T> implements Call<T> {
final Executor callbackExecutor;
final Call<T> delegate;

ExecutorCallbackCall(Executor callbackExecutor, Call<T> delegate) {
this.callbackExecutor = callbackExecutor;
this.delegate = delegate;
}

@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");

delegate.enqueue(new Callback<T>() {
@Override public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
if (delegate.isCanceled()) {
// Emulate OkHttp's behavior of throwing/delivering an IOException on cancellation.
callback.onFailure(ExecutorCallbackCall.this, new IOException("Canceled"));
} else {
callback.onResponse(ExecutorCallbackCall.this, response);
}
}
});
}

@Override public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.onFailure(ExecutorCallbackCall.this, t);
}
});
}
});
}

@Override public boolean isExecuted() {
return delegate.isExecuted();
}

@Override public Response<T> execute() throws IOException {
return delegate.execute();
}

@Override public void cancel() {
delegate.cancel();
}

@Override public boolean isCanceled() {
return delegate.isCanceled();
}

@SuppressWarnings("CloneDoesntCallSuperClone") // Performing deep clone.
@Override public Call<T> clone() {
return new ExecutorCallbackCall<>(callbackExecutor, delegate.clone());
}

@Override public Request request() {
return delegate.request();
}
}
这个类通过delegate的enqueue去请求数据,delegate对象实质上就是serviceMethod.callAdapter.adapt(okHttpCall)这行中的okHttpCall对象,由adapt()这个方法设置进去。这里面的callbackExecutor是上面Platform类Android()方法中识别在Android平台而创建的MainThreadExecutor对象,此对象存放在了主线程的消息队列,在这里执行MainThreadExecutor通过callback回调到UI线程,从而有成功onResponse和失败onFailure两个回调。接着我们看下delegate.enqueue,实际就是okHttpCall中的enqueue:


@Override public void enqueue(final Callback<T> callback) {
if (callback == null) throw new NullPointerException("callback == null");

okhttp3.Call call;
Throwable failure;

synchronized (this) {
if (executed) throw new IllegalStateException("Already executed.");
executed = true;

call = rawCall;
failure = creationFailure;
if (call == null && failure == null) {
try {
call = rawCall = createRawCall();
} catch (Throwable t) {
failure = creationFailure = t;
}
}
}

if (failure != null) {
callback.onFailure(this, failure);
return;
}

if (canceled) {
call.cancel();
}

call.enqueue(new okhttp3.Callback() {
@Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
throws IOException {
Response<T> response;
try {
response = parseResponse(rawResponse);
} catch (Throwable e) {
callFailure(e);
return;
}
callSuccess(response);
}

@Override public void onFailure(okhttp3.Call call, IOException e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}

private void callFailure(Throwable e) {
try {
callback.onFailure(OkHttpCall.this, e);
} catch (Throwable t) {
t.printStackTrace();
}
}

private void callSuccess(Response<T> response) {
try {
callback.onResponse(OkHttpCall.this, response);
} catch (Throwable t) {
t.printStackTrace();
}
}
});
}
这里面有这个方法createRawCall()方法:


private okhttp3.Call createRawCall() throws IOException {
Request request = serviceMethod.toRequest(args);
okhttp3.Call call = serviceMethod.callFactory.newCall(request);
if (call == null) {
throw new NullPointerException("Call.Factory returned null.");
}
return call;
}
createRawCall()返回okHttp3.Call对象,也就是用的okHttp3.Call对象来执行的请求。在createRawCall()中,通过serviceMethod.toRequest(args)得到请求的url,上面也提到了ServiceMethod的toRequest方法通过parameterHandler的apply方法构造一个完整的request,到此,一个请求的线路就说完了。下面接着看响应的内容:这里有一行response = parseResponse(rawResponse);



Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
ResponseBody rawBody = rawResponse.body();

// Remove the body's source (the only stateful object) so we can pass the response along.
rawResponse = rawResponse.newBuilder()
.body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
.build();

int code = rawResponse.code();
if (code < 200 || code >= 300) {
try {
// Buffer the entire body to avoid future I/O.
ResponseBody bufferedBody = Utils.buffer(rawBody);
return Response.error(bufferedBody, rawResponse);
} finally {
rawBody.close();
}
}

if (code == 204 || code == 205) {
return Response.success(null, rawResponse);
}

ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
try {
T body = serviceMethod.toResponse(catchingBody);
return Response.success(body, rawResponse);
} catch (RuntimeException e) {
// If the underlying source threw an exception, propagate that rather than indicating it was
// a runtime exception.
catchingBody.throwIfCaught();
throw e;
}
}
在return的地方,T body = serviceMethod.toResponse(catchingBody);


/** Builds a method return value from an HTTP response body. */
T toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
其实就是通过serviceMethod的toResponse将请求返回的数据用我们的converter进行转化,这个转化器就是开篇我们设置进去的GsonConverterFactory。到此整个源码分析就结束了,重新整理下:我们将页面上接口传给Retrofit,Retrofit通过Java动态代理去对接口中方法和注解进行解析,在Retrofit创建的时候,根据Java平台默认创建Executor,并将此Executor存放在主线程的消息队列,在Retrofit创建中,创建了最重要的serviceMethod类,serviceMethod类将对方法和注解进行解析拼接成请求的url,并对返回的数据做转换处理。创建的OkHttpCall对象就实质上还是用的okHttp3.Call对象去执行的请求,通过serviceMethod.toRequest(args)得到的url请求,得到数据后由serviceMethod设置的转化器解析数据。最终callback以回调的方式将数据给UI界面。总算是明朗了很多,开源框架在使用的同时,看一看实现的源码,收获很多,这里的Java动态代理使用得很精髓,包括平台的判断创建线程执行的地方等等,看的过程好痛苦,但是看通了就豁然开朗了很多,但愿这对看这篇博客的朋友有一点帮助。最后谢谢大家支持!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Retrofit2.0 源码