Android网络之Retrofit2.0使用和解析
Retrofit2在项目中的使用
Androidstudio项目添加依赖
compile''com.squareup.retrofit2:retrofit:2.0.1''
项目中使用样例
定义HTTPAPI使用接口
publicinterfaceGitHubService{
@GET("users/{user}/repos")
Call>listRepos(@Path("user")Stringuser);
}
通过在接口上添加注解的方式来表示如何处理网络请求。
Retrofit支持5中类型的注解:GET,POST,PUT,DELETE和HEAD.
可以使用不带参数的urljava@GET("users/list"),也可以使用带参数的urljava@GET("users/list?sort=desc")
构造Retrofit实例
Retrofitretrofit=newRetrofit.Builder()
.baseUrl("https://api.github.com/")
.build();
GitHubServiceservice=retrofit.create(GitHubService.class);
创建同步或异步HTTP请求到远程网络服务器
Call>repos=service.listRepos("octocat");
定制数据类型转换器
Gson:com.squareup.retrofit2:converter-gson
Jackson:com.squareup.retrofit2:converter-jackson
Moshi:com.squareup.retrofit2:converter-moshi
Protobuf:com.squareup.retrofit2:converter-protobuf
Wire:com.squareup.retrofit2:converter-wire
SimpleXML:com.squareup.retrofit2:converter-simplexml
Scalars(primitives,boxed,andString):com.squareup.retrofit2:converter-scalars
Retrofitretrofit=newRetrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.build();
GitHubServiceservice=retrofit.create(GitHubService.class);
Retrofit使用扩展
自定义Gson类型转换器
/
{
"resultcode":0,
"resultmsg":"请求成功",
"result":{}
}
/
publicclassWrapper{
publicintresultcode;
publicStringresultmsg;
publicObjectresult;
publicstaticclassJsonAdapterimplementsJsonDeserializer{
@Override
publicWrapperdeserialize(JsonElementjson,TypetypeOfT,JsonDeserializationContextcontext)throwsJsonParseException{
try{
StringjsonRoot=json.getAsJsonObject().toString();
Wrapperwrapper=newWrapper();
JSONObjectjsobRespData=newJSONObject(jsonRoot);
wrapper.resultcode=jsobRespData.getInt("resultcode");
wrapper.resultmsg=jsobRespData.getString("resultmsg");
wrapper.result=jsobRespData.get("result");
returnwrapper;
}catch(JSONExceptione){
thrownewJsonParseException(e);
}
}
}
添加到Retrofit当中
Gsongson=newGsonBuilder()
.registerTypeAdapter(Wrapper.class,newWrapper.JsonAdapter())
.create();
Retrofitretrofit=newRetrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
GitHubServiceservice=retrofit.create(GitHubService.class);
请求时添加head信息
在定义请求接口时添加:
@Headers("Cache-Control:max-age=640000")
@GET("widget/list")
Call>widgetList();
@Headers({
"Accept:application/vnd.github.v3.full+json",
"User-Agent:Retrofit-Sample-App"
})
@GET("users/{username}")
CallgetUser(@Path("username")Stringusername);
@GET("user")
CallgetUser(@Header("Authorization")Stringauthorization)
Retrofit依赖
如果所示在Retrofit2.0中只支持okhttp,所以另一种方法是在okhttp的拦截器中addheader。
Retrofit2源码解析
Retrofit请求框架实现了高度的解耦,通过解析注解的得到的代理类生成http请求,然后将请求交给OkHttp。通过在Retrofit创建时生成的Converter再将OkHttp返回的数据进行类型转换得到自己需要的数据。现在Rxjava响应式编程已经广泛应用,在使用Retrofit时也会结合RxJava使编码更加简单、高效。
一张图简单描述一下Retrofit的工作原理:
Retrofit工作原理
定义网络请求接口
publicinterfaceGitHubService{
@GET("users/{user}/repos")
Call>listRepos(@Path("user")Stringuser);
}
创建Retrofit实例
Retrofitretrofit=newRetrofit.Builder()
.baseUrl("https://api.github.com")
//支持RxJava
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(ByteArrayConverterFactory.create())
.addConverterFactory(JSONObjectResponseConverterFactory.create())
.addConverterFactory(StringResponseConverterFactory.create())
//支持对象转json串
.addConverterFactory(GsonConverterFactory.create())
.build();
设置BaseUrl
添加CallAdapterFactory
添加converterFactory
此时也可以设置自定义的okHttpclient
接下来我们看
GitHubServiceservice=retrofit.create(GitHubService.class);
Retrofit.create方法的详细介绍
publicTcreate(finalClassservice){
//判断定义的接口服务是否可用
Utils.validateServiceInterface(service);
if(validateEagerly){
eagerlyValidateMethods(service);
}
return(T)Proxy.newProxyInstance(service.getClassLoader(),newClass>[]{service},
newInvocationHandler(){
//判断Android,IOS,java8
privatefinalPlatformplatform=Platform.get();
@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object...args)
throwsThrowable{
//如果是对象里的方法直接调用
if(method.getDeclaringClass()==Object.class){
returnmethod.invoke(this,args);
}
/
对java8做兼容,android和ios值恒为false
/
if(platform.isDefaultMethod(method)){
returnplatform.invokeDefaultMethod(method,service,proxy,args);
}
//主要看这三行代码
/
1、生成获取缓存中的method对应的ServiceMethod或者生产method对应的ServiceMethod
2、生成OkHttpCall的实例
3、根据生成的ServiceMethod实例中的callAdapter对象,调用callAdapter.adapt方法创建
对应的Observable
/
ServiceMethodserviceMethod=loadServiceMethod(method);
OkHttpCallokHttpCall=newOkHttpCall<>(serviceMethod,args);
returnserviceMethod.callAdapter.adapt(okHttpCall);
}
Platfrom的获取
Platfrom
classPlatform{
//这个方法Android中为Plafrom默认的
//Java8返回的是method.isDefault(),熟悉Java8的都知道这是Java8的新特性。。
booleanisDefaultMethod(Methodmethod){
returnfalse;
}
//这个方法Android中有自己默认的实现MainThreadExecutor
ExecutordefaultCallbackExecutor(){
returnnull;
}
staticclassAndroidextendsPlatform{
@Override
publicExecutordefaultCallbackExecutor(){
returnnewMainThreadExecutor();
}
@Override
CallAdapter.FactorydefaultCallAdapterFactory(ExecutorcallbackExecutor){
returnnewExecutorCallAdapterFactory(callbackExecutor);
}
//Rx默认请求方式都是同步请求,所以我们在发出请求和请求结果回来的时候切换线程
staticclassMainThreadExecutorimplementsExecutor{
privatefinalHandlerhandler=newHandler(Looper.getMainLooper());
@Override
publicvoidexecute(Runnabler){
handler.post(r);
}
}
}
ServiceMethod对象的生成
先看一张我debug时候的ServiceMethod的图
ServiceMethod
ServiceMethod的获取
/Retrofit.java
首先从serviceMethodCache缓存中获取,如果为null则创建
/
ServiceMethodloadServiceMethod(Methodmethod){
ServiceMethodresult;
synchronized(serviceMethodCache){
result=serviceMethodCache.get(method);
if(result==null){
result=newServiceMethod.Builder(this,method).build();
serviceMethodCache.put(method,result);
}
}
returnresult;
}
ServiceMethod的创建
finalclassServiceMethod{
//部分代码省略
ServiceMethod(Builderbuilder){
this.callFactory=builder.retrofit.callFactory();
this.callAdapter=builder.callAdapter;
this.baseUrl=builder.retrofit.baseUrl();
this.responseConverter=builder.responseConverter;
this.httpMethod=builder.httpMethod;
this.relativeUrl=builder.relativeUrl;
this.headers=builder.headers;
this.contentType=builder.contentType;
this.hasBody=builder.hasBody;
this.isFormEncoded=builder.isFormEncoded;
this.isMultipart=builder.isMultipart;
this.parameterHandlers=builder.parameterHandlers;
}
staticfinalclassBuilder{
publicBuilder(Retrofitretrofit,Methodmethod){
this.retrofit=retrofit;
this.method=method;
this.methodAnnotations=method.getAnnotations();
this.parameterTypes=method.getGenericParameterTypes();
this.parameterAnnotationsArray=method.getParameterAnnotations();
}
publicServiceMethodbuild(){
//创建CallAdapter>
callAdapter=createCallAdapter();
responseType=callAdapter.responseType();
if(responseType==Response.class||responseType==okhttp3.Response.class){
throwmethodError("''"
+Utils.getRawType(responseType).getName()
+"''isnotavalidresponsebodytype.DidyoumeanResponseBody?");
}
//创建Converter
responseConverter=createResponseConverter();
for(Annotationannotation:methodAnnotations){
parseMethodAnnotation(annotation);
}
//
returnnewServiceMethod<>(this);
}
privateCallAdapter>createCallAdapter(){
TypereturnType=method.getGenericReturnType();
//
Annotation[]annotations=method.getAnnotations();
try{
//调用retrofit中的方法进行创建
returnretrofit.callAdapter(returnType,annotations);
}catch(RuntimeExceptione){//Wideexceptionrangebecausefactoriesareusercode.
throwmethodError(e,"Unabletocreatecalladapterfor%s",returnType);
}
}
privateConvertercreateResponseConverter(){
Annotation[]annotations=method.getAnnotations();
try{
//调用retrofit中的方法进行创建
returnretrofit.responseBodyConverter(responseType,annotations);
}catch(RuntimeExceptione){//Wideexceptionrangebecausefactoriesareusercode.
throwmethodError(e,"Unabletocreateconverterfor%s",responseType);
}
}
}
CallAdapter的创建
publicCallAdapter>callAdapter(TypereturnType,Annotation[]annotations){
returnnextCallAdapter(null,returnType,annotations);
}
publicCallAdapter>nextCallAdapter(CallAdapter.FactoryskipPast,TypereturnType,
Annotation[]annotations){
checkNotNull(returnType,"returnType==null");
checkNotNull(annotations,"annotations==null");
intstart=adapterFactories.indexOf(skipPast)+1;
for(inti=start,count=adapterFactories.size();i CallAdapter>adapter=adapterFactories.get(i).get(returnType,annotations,this);
if(adapter!=null){
returnadapter;
}
}
//
}
在创建Retrofit的时候我们添加过.addCallAdapterFactory(RxJavaCallAdapterFactory.create()),这是我们会调用RxJavaCallAdapterFactory.get方法获取CallAdapter,通过源代码我们可以找到其返回的是newSimpleCallAdapter(observableType,scheduler)。
Converter的创建
publicConverterrequestBodyConverter(Typetype,
Annotation[]parameterAnnotations,Annotation[]methodAnnotations){
returnnextRequestBodyConverter(null,type,parameterAnnotations,methodAnnotations);
}
publicConverternextRequestBodyConverter(Converter.FactoryskipPast,
Typetype,Annotation[]parameterAnnotations,Annotation[]methodAnnotations){
checkNotNull(type,"type==null");
checkNotNull(parameterAnnotations,"parameterAnnotations==null");
checkNotNull(methodAnnotations,"methodAnnotations==null");
intstart=converterFactories.indexOfwww.wang027.com(skipPast)+1;
for(inti=start,count=converterFactories.size();i Converter.Factoryfactory=converterFactories.get(i);
Converter,RequestBody>converter=
factory.requestBodyConverter(type,parameterAnnotations,methodAnnotations,this);
if(converter!=null){
//noinspectionunchecked
return(Converter)converter;
}
}
//
相同的在创建Retrofit的时候我们也添加过许多的ConverterFactory,在寻找相匹配的Converter时我们是通过遍历在寻找到第一个合适的Converter返回。什么叫做合适的Converter,即该ConverterFactory能产生出匹配服务接口注解和返回类型。
retrofit的构造器中默认添加的适配器和转化器
publicstaticfinalclassBuilder{
privatePlatformplatform;
privateokhttp3.Call.FactorycallFactory;
privateHttpUrlbaseUrl;
privateListconverterFactories=newArrayList<>();
privateListadapterFactories=newArrayList<>();
privateExecutorcallbackExecutor;
privatebooleanvalidateEagerly;
Builder(Platformplatform){
this.platform=platform;
//Addthebuilt-inconverterfactoryfirst.Thispreventsoverridingitsbehaviorbutalso
//ensurescorrectbehaviorwhenusingconvertersthatconsumealltypes.
//自动回添加加默认的转化器
converterFactories.add(newBuiltInConverters());
}
//
publicRetrofitbuild(){
if(baseUrl==null){
thrownewIllegalStateException("BaseURLrequired.");
}
okhttp3.Call.FactorycallFactory=this.callFactory;
if(callFactory==null){
callFactory=newOkHttpClient();
}
ExecutorcallbackExecutor=this.callbackExecutor;
if(callbackExecutor==null){
callbackExecutor=platform.defaultCallbackExecutor();
}
//MakeadefensivecopyoftheadaptersandaddthedefaultCalladapter.
ListadapterFactories=newArrayList<>(this.adapterFactories);
//添加一个默认的适配器(Android、IOS、Java8)
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
//Makeadefensivecopyoftheconverters.
ListconverterFactories=newArrayList<>(this.converterFactories);
returnnewRetrofit(callFactory,baseUrl,converterFactories,adapterFactories,
callbackExecutor,validateEagerly);
具体怎么从Factory中获取对应的Converter和Adapter我们从代码中可以直观的看到。
OkHttpCall的创建
OkHttpCall(ServiceMethodserviceMethod,Object[]args){
this.serviceMethod=serviceMethod;
this.args=args;
}
网络请求
请求的准备
serviceMethod.callAdapter.adapt(okHttpCall)对应SimpleCallAdapter.adapt
staticfinalclassSimpleCallAdapterimplementsCallAdapter>{
privatefinalTyperesponseType;
privatefinalSchedulerscheduler;
SimpleCallAdapter(TyperesponseType,Schedulerscheduler){
this.responseType=responseType;
this.scheduler=scheduler;
}
@OverridepublicTyperesponseType(){
returnresponseType;
}
@OverridepublicObservableadapt(Callcall){
//创建请求的观察者,返回我们需要的Ovservable
Observableobservable=Observable.create(newCallOnSubscribe<>(call))//
.lift(OperatorMapResponseToBodyOrError.instance());
if(scheduler!=null){
returnobservable.subscribeOn(scheduler);
}
returnobservable;
}
staticclassAndroidextendsPlatform{
@Override
publicExecutordefaultCallbackExecutor(){
returnnewMainThreadExecutor();
}
@Override
CallAdapter.FactorydefaultCallAdapterFactory(ExecutorcallbackExecutor){
returnnewExecutorCallAdapterFactory(callbackExecutor);
}
staticclassMainThreadExecutorimplementsExecutor{
privatefinalHandlerhandler=newHandler(Looper.getMainLooper());
@Override
publicvoidexecute(Runnabler){
handler.post(r);
}
}
}
/
因为默认的执行线程为主线程,所以我们要切换到subscribeOn(Schedulers.io())线程从而达到异步的目的。
然后通过observeOn(AndroidSchedulers.mainThread())将线程切回UI线程。
当Okhttp请求完数据并进行相应的convert之后,就可以在UI处理相应的逻辑。
/
service.listRepos("octocat")
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(list->{
if(list!=null){
//TODO取得数据后逻辑处理
}
请求的发起
回到CallAdapt方法,创建Observable,而newCallOnSubscribe<>(call)生成了一个OnSubscribe()的实例,而OnSubscribe继承自Action1,其只包含一个call()方法,而这个call是在CallOnSubscribe中实现:
staticfinalclassCallOnSubscribeimplementsObservable.OnSubscribe>{
privatefinalCalloriginalCall;
CallOnSubscribe(CalloriginalCall){
this.originalCall=originalCall;
}
@Overridepublicvoidcall(finalSubscriber>subscriber){
//SinceCallisaone-shottype,cloneitforeachnewsubscriber.
Callcall=originalCall.clone();
//Wrapthecallinahelperwhichhandlesbothunsubscriptionandbackpressure.
RequestArbiterrequestArbiter=newRequestArbiter<>(call,subscriber);
subscriber.add(Subscriptions.create(requestArbiter));
subscriber.setProducer(requestArbiter);
首先clone了一份Call,然后生成了RequestArbiter,他继承自AtomicBoolean,实现了Subscription,Producer接口,Producer只有一个request方法;一般实现该接口的类,都会包含一个Subscriber对象和一个待处理的数据:
staticfinalclassRequestArbiterextendsAtomicBooleanimplementsAction0,
Producer{
privatefinalCallcall;
privatefinalSubscriber>subscriber;
RequestArbiter(Callcall,Subscriber>subscriber){
this.call=call;
this.subscriber=subscriber;
}
@Override
publicvoidrequest(longn){
if(n<0){
thrownewIllegalArgumentException("n<0:"+n);
}
if(n==0){
return;//Nothingtodowhenrequesting0.
}
if(!compareAndSet(false,true)){
return;//Requestwasalreadytriggered.
}
try{
//进行网络请求
Responseresponse=call.execute();
if(!subscriber.isUnsubscribed()){
subscriber.onNext(response);
}
}catch(Throwablet){
Exceptions.throwIfFatal(t);
if(!subscriber.isUnsubscribed()){
subscriber.onError(t);
}
return;
}
if(!subscriber.isUnsubscribed()){
subscriber.onCompleted();
}
}
@Override
publicvoidcall(){
call.cancel();
}
请求的执行
回顾创建Retrofit.create()代码中serviceMethod.callAdapter.adapt(okHttpCall),所以上面的call.execute()就是OkHttpCall.execute
publicResponseexecute()throwsIOException{
okhttp3.Callcall;
synchronized(this){
if(executed)
thrownewIllegalStateException("Alreadyexecuted.");
executed=true;
if(creationFailure!=null){
if(creationFailureinstanceofIOException){
throw(IOException)creationFailure;
}else{
throw(RuntimeException)creationFailure;
}
}
call=rawCall;
if(call==null){
try{
//获取okhttp实例
call=rawCall=createRawCall();
}catch(IOException|RuntimeExceptione){
creationFailure=e;
throwe;
}
}
}
if(canceled){
call.cancel();
}
//执行okhttp请求
return(parseResponse(call.execute()));
}
privateokhttp3.CallcreateRawCall()throwsIOException{
Requestrequest=serviceMethod.toRequest(args);
//serviceMethod构造中this.callFactory=builder.retrofit.callFactory();
okhttp3.Callcall=serviceMethod.callFactory.newCall(request);
if(call==null){
thrownewNullPointerException("Call.Factoryreturnednull.");
}
return(call);
请求的OkHttpClient实例获取
publicokhttp3.Call.FactorycallFactory(){
returncallFactory;
}
publicBuildercallFactory(okhttp3.Call.Factoryfactory){
this.callFactory=checkNotNull(factory,"factory==null");
returnthis;
}
//使用自定义OkHttpClient
publicBuilderclient(OkHttpClientclient){
returncallFactory(checkNotNull(client,"client==null"));
}
publicRetrofitbuild(){
if(baseUrl==null){
thrownewIllegalStateException("BaseURLrequired.");
}
okhttp3.Call.FactorycallFactory=this.callFactory;
//没有自定义OkHttpClient,则会新创建一个
if(callFactory==null){
callFactory=newOkHttpClient();
}
ExecutorcallbackExecutor=this.callbackExecutor;
if(callbackExecutor==null){
callbackExecutor=platform.defaultCallbackExecutor();
}
ListadapterFactories=newArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
ListconverterFactories=newArrayList<>(this.converterwww.baiyuewang.netFactories);
return(newRetrofit(callFactory,baseUrl,converterFactories,adapterFactories,
callbackExecutor,validateEagerly));
}
}
请求结果的处理
ResponseparseResponse(okhttp3.ResponserawResponse)throwsIOException{
ResponseBodyrawBody=rawResponse.body();
rawResponse=rawResponse.newBuilder()
.body(newNoContentResponseBody(rawBody.contentType(),rawBody.contentLength()))
.build();
intcode=rawResponse.code();
if(code<200||code>=300){
try{
ResponseBodybufferedBody=Utils.buffer(rawBody);
return(Response.error(bufferedBody,rawResponse));
}finally{
rawBody.close();
}
}
if(code==204||code==205){
return(Response.success(null,rawResponse));
}
ExceptionCatchingRequestBodycatchingBody=newExceptionCatchingRequestBody(rawBody);
try{
//使用Converter将返回结果转化为接口返回的数据格式类型
Tbody=serviceMethod.toResponse(catchingBody);
//包装成Response并返回
return(Response.success(body,rawResponse));
}catch(RuntimeExceptione){
catchingBody.throwIfCaught();
throwe;
}
还记得创建Observable时Observableobservable=Observable.create(newCallOnSubscribe<>(call)).lift(OperatorMapResponseToBodyOrError.instance());,OperatorMapResponseToBodyOrError将包装的Response中的body取出来并进行发射。
总结
现在随着Rxjava响应式编程越来越多的程序猿使用,自己也开始接触和使用。Retrofit+Rxjava+okhttp是时下比较受欢迎的网络请求框架,其源代码并不是很多,其底层网络通信时交由OkHttp来完成的,但是Retrofit运用了大量的设计模式,代码逻辑很清晰,笔者以前用的是AsyncHttpClient作为app的网络请求框架,其源码也没自己的研究过。但看完Retrofit代码之后觉得收获很大,建议如果感兴趣可以抽时间仔细的阅读。
|
|