一.分析源码的基本姿势
抽茧剥丝看本质
网络请求流程.png
二.Retrofit是什么,有哪些API,有什么好处(what)
1.先看Retrofit的文档https://square.github.io/retrofit/
A type-safe HTTP client for Android and Java 这里看这个 type-safe,Retrofit通过泛型来约束我们想要的对象,自己不用去解析数据
例子:
public class MainActivity extends AppCompatActivity {
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text_content);
}
public void getHtttp(View view) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://gank.io/")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubService gitHubService = retrofit.create(GitHubService.class);
Call<BaseModel<ArrayList<Benefit>>> call = gitHubService.defautBenefits(20, 1);
call.enqueue(new Callback<BaseModel<ArrayList<Benefit>>>() {
@Override
public void onResponse(Call<BaseModel<ArrayList<Benefit>>> call, Response<BaseModel<ArrayList<Benefit>>> response) {
textView.setText(response.body().results.get(0).getDesc());
}
@Override
public void onFailure(Call<BaseModel<ArrayList<Benefit>>> call, Throwable t) {
}
});
}
}
public interface GitHubService {
@GET("api/data/福利/{pageCount}/{pageIndex}")
Call<BaseModel<ArrayList<Benefit>>> defautBenefits(
@Path("pageCount") int pageCount,
@Path("pageIndex") int pageIndex
);
}
public class BaseModel<T> {
public boolean error;
public T results;
}
public class Benefit {
/**
* _id : 5a8e0c41421aa9133298a259
* createdAt : 2018-02-22T08:18:09.547Z
* desc : 2-22
* publishedAt : 2018-02-22T08:24:35.209Z
* source : chrome
* type : 福利
* url : https://ws1.sinaimg.cn/large/610dc034ly1foowtrkpvkj20sg0izdkx.jpg
* used : true
* who : 代码家
*/
private String _id;
private String createdAt;
private String desc;
private String publishedAt;
private String source;
private String type;
private String url;
private boolean used;
private String who;
public String get_id() {
return _id;
}
public void set_id(String _id) {
this._id = _id;
}
public String getCreatedAt() {
return createdAt;
}
public void setCreatedAt(String createdAt) {
this.createdAt = createdAt;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
public String getPublishedAt() {
return publishedAt;
}
public void setPublishedAt(String publishedAt) {
this.publishedAt = publishedAt;
}
public String getSource() {
return source;
}
public void setSource(String source) {
this.source = source;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public boolean isUsed() {
return used;
}
public void setUsed(boolean used) {
this.used = used;
}
public String getWho() {
return who;
}
public void setWho(String who) {
this.who = who;
}
}
三.debug拎出主线逻辑(how)
debug!debug!debug!
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("http://gank.io/")
.addConverterFactory(GsonConverterFactory.create())
.build();
retrofit 通过Builder模式来创建,先看看build()方法
public Retrofit build() {
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
1.okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
2.Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// Make a defensive copy of the adapters and add the default Call adapter.
3.List<CallAdapter.Factory> adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// Make a defensive copy of the converters.
4. List<Converter.Factory> converterFactories = new ArrayList<>(this.converterFactories);
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
1.这里先判断callFactory 是否为空,如果为空,则new一个OkHttpClient,那为什么callFactory 只判断是否为空,没有判断callFactory的值呢?这里的工厂模式已经没有意义了,显而易见,Retrofit现在只支持OkHttpClient,不支持HttpClient和HttpConnection
2.如果没有给我传入Executor ,这里new一个Executor
static class Android extends Platform {
@Override public Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
@Override CallAdapter.Factory defaultCallAdapterFactory(@Nullable Executor callbackExecutor) {
if (callbackExecutor == null) throw new AssertionError();
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);
}
}
}
在MainThreadExecutor 中,我们声明了一个Handler,创建时我们传入了Looper.getMainLooper(),这里Handler在主线程中运行,execute()方法也在主线程中执行。
3.把封装的Call转换成我们想要的Call对象(适配器模式)
4.converterFactories断点调试可以看出是GsonConvertFactory
最后构建成一个Retrofit。
再看看retrofit.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();
//当调用api方法时,就会触发invoke
@Override public Object invoke(Object proxy, Method method, @Nullable 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);
}
//通过对注解的处理转换成我们想要的参数
//dapts an invocation of an interface method into an HTTP call.
//例如:pageCount=20 pageIndex=1
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
//转换成OkHttpCall
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
//利用adapt方法,转换成我们想要的call
//例如: Call<BaseModel<ArrayList<Benefit>>> 我们返回call
//在rxJava中返回Observebal
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}
最后返回的call调用enqueue方法
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
//代理delegate其实就是call
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);
}
});
}
});
}
总结一下:
Retrofit build
Retrofit create proxy for API interface
API method intercepted by proxy
parse params with ServiceMethod
build HttpCall with params
CallAdapter adapts Call to T
enqueue() waiting for callback
四.直接看源码,画流程图
ServiceMethod<Object, Object> serviceMethod =
(ServiceMethod<Object, Object>) loadServiceMethod(method);
在动态代理中,loadServiceMethod()会不会频繁的解析注解呢?
ServiceMethod<?, ?> loadServiceMethod(Method method) {
//看到serviceMethodCache就可以断定,有缓存
//解析过的不会再解析了
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;
}
OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
我们解析取来的注解参数,最后怎么能弄成我们想要的Okhttp的格式呢?serviceMethod传入了OkHttpCall类中
看看OkHttpCall这个类,实现Call这个接口,接口Call中有同步请求、异步请求、取消、判断是否取消状态。OkHttpCall里面,对参数进行了包装(Request、RequestBody、OkHttp...),变成想要的OkHttpCall了。
这行代码有点绕(= =)
return serviceMethod.callAdapter.adapt(okHttpCall);
先see see serviceMethod.callAdapter.怎么来的
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);
}
.......
省略代码了
.......
private CallAdapter<T, R> 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 (CallAdapter<T, R>) 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);
}
}
public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,
Annotation[] annotations) {
checkNotNull(returnType, "returnType == null");
checkNotNull(annotations, "annotations == null");
int start = adapterFactories.indexOf(skipPast) + 1;
//对于CallAdapter我们在Retrofit build的时候把它初始化
//在这里取出相应的adapter,如果我们不添加,默认的是ExecutorCallAdapterFactory
//如果想配合RxJava使用(又是一种类型)
//addCallAdapterFactory(RxJavaCallAdapterFactory.create())
//还要Java8、、、
for (int i = start, count = adapterFactories.size(); i < count; i++) {
CallAdapter<?, ?> adapter = adapterFactories.get(i).get(returnType, annotations, this);
if (adapter != null) {
return adapter;
}
}
StringBuilder builder = new StringBuilder("Could not locate call adapter for ")
.append(returnType)
.append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(adapterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = adapterFactories.size(); i < count; i++) {
builder.append("\n * ").append(adapterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
}
然后再调用adapt()方法,看一下ExecutorCallAdapterFactory中的方法
@Override
// Android中默认返回的是Call,在RxJava中返回Observable
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call.class) {
return null;
}
final Type responseType = Utils.getCallResponseType(returnType);
return new CallAdapter<Object, Call<?>>() {
@Override public Type responseType() {
return responseType;
}
@Override public Call<Object> adapt(Call<Object> call) {
//这里传递进来的是OkHttpCall
return new ExecutorCallbackCall<>(callbackExecutor, call);
}
};
}
serviceMethod.callAdapter.adapt(okHttpCall)返回ExecutorCallbackCall,Retrofit的create也返回了ExecutorCallbackCall,这样Call<BaseModel<ArrayList<Benefit>>> call开始调用enqueue()方法了
@Override public void enqueue(final Callback<T> callback) {
checkNotNull(callback, "callback == null");
//其实就是okhttpcall调用的enqueue方法
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);
}
});
}
});
}
进入OkHttpCall里面的方法,和Retrofit无关了
在RealCall里面的代码
@Override public void enqueue(Callback responseCallback) {
synchronized (this) {
if (executed) throw new IllegalStateException("Already Executed");
executed = true;
}
captureCallStackTrace();
//看这里 enqueue方法时异步方法!!!
client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
最后,callback回调到最上层,我们还要找一下如何通过conventer来转换的?
先看response
OkHttpCall的类中的enqueue()方法
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) {
rawBody.close();
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;
}
}
R toResponse(ResponseBody body) throws IOException {
return responseConverter.convert(body);
}
具体是GsonRequestBodyConverter来实现的,转换成我们需要的T
@Override public T convert(ResponseBody value) throws IOException {
JsonReader jsonReader = gson.newJsonReader(value.charStream());
try {
return adapter.read(jsonReader);
} finally {
value.close();
}
}
}
再来看看request(把注解转换成参数)OkhttpCall类
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;
}
ServiceMethod类
Request toRequest(@Nullable Object... args) throws IOException {
//我们看看RequestBuilder中的RequestBody
RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
contentType, hasBody, isFormEncoded, isMultipart);
@SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;
int argumentCount = args != null ? args.length : 0;
if (argumentCount != handlers.length) {
throw new IllegalArgumentException("Argument count (" + argumentCount
+ ") doesn't match expected count (" + handlers.length + ")");
}
for (int p = 0; p < argumentCount; p++) {
handlers[p].apply(requestBuilder, args[p]);
}
return requestBuilder.build();
}
RequestBuilder类
void setBody(RequestBody body) {
this.body = body;
}
我们看看这个方法在哪里被调用了
ParameterHandler类
@Override void apply(RequestBuilder builder, @Nullable T value) {
if (value == null) {
throw new IllegalArgumentException("Body parameter value must not be null.");
}
RequestBody body;
try {
// !!!!!!!!在这里 GsonResponseBodyConverter实现了这个方法
body = converter.convert(value);
} catch (IOException e) {
throw new RuntimeException("Unable to convert " + value + " to RequestBody", e);
}
builder.setBody(body);
}
流程图.jpg
网友评论