【移动应用开发技术】Android 中Retrofit源码如何使用_第1页
【移动应用开发技术】Android 中Retrofit源码如何使用_第2页
【移动应用开发技术】Android 中Retrofit源码如何使用_第3页
【移动应用开发技术】Android 中Retrofit源码如何使用_第4页
【移动应用开发技术】Android 中Retrofit源码如何使用_第5页
免费预览已结束,剩余2页可下载查看

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

【移动应用开发技术】Android中Retrofit源码如何使用

这期内容当中在下将会给大家带来有关Android中Retrofit源码如何使用,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。简介Retrofit是Square推出的HTTP框架,主要用于Android和Java。Retrofit

将网络请求变成方法的调用,使用起来非常简洁方便。本文先简要介绍一下Retrofit的用法,然后具体分析其源码执行的流程。基本用法Retrofit把HTTPAPI变成Java的接口。下面是Retrofit官网的一个例子:public

interface

GitHubService

{

@GET("users/{user}/repos")

Call<List<Repo>>

listRepos(@Path("user")

String

user);

}在GithubService接口中有一个方法listRepos,这个方法用了@GET的方式注解,这表明这是一个GET

请求。在后面的括号中的users/{user}/repos是请求的路径,其中的{user}

表示的是这一部分是动态变化的,它的值由方法的参数传递过来,而这个方法的参数@Path("user")Stringuser即是用于替换{user}

。另外注意这个方法的返回值是Call<List<Repo>>。可以看出Retrofit

用注解的方式来描述一个网络请求相关的参数。上面才是开始,下面要发出这个网络请求:Retrofit

retrofit

=

new

Retrofit.Builder()

.baseUrl("/")

.addConverterFactory(GsonConverterFactory.create())

.build();

GitHubService

service

=

retrofit.create(GitHubService.class);

Call<List<Repo>>

repos

=

service.listRepos("octocat");

repos.enqueue(new

Callback<List<Repo>>()

{

@Override

public

void

onResponse(Call<List<Repo>>

call,

Response<List<Repo>>

response)

{

}

@Override

public

void

onFailure(Call<List<Repo>>

call,

Throwable

t)

{

}

});可以看出,先是构建了一个Retrofit对象,其中传入了baseUrl参数,baseUrl和上面的GET方法后面的路径组合起来才是一个完整的

url。除了baseUrl,还有一个converterFactory,它是用于把返回的httpresponse转换成Java

对象,对应方法的返回值Call<List<Repo>>中的List<Repo>>,其中Repo

是自定义的类。有了Retrofit对象,接着调用它的create方法创建了GitHubService

的实例,然后就可以调用这个实例的方法来请求网络了。调用listRepo方法得到一个Call对象,然后可以使用enqueue或者execute

来执行发起请求,enqueue是是异步执行,而execute是同步执行。Retrofit的基本用法就是这样,其它还有一些细节可以查看官网。源码分析我***次接触Retrofit的时候觉得这个东西挺神奇的,用法跟一般的网络请求不一样。下面就来看看Retrofit的源码是怎么实现的。Retrofit的创建从Retrofit的创建方法可以看出,使用的是Builder模式。Retrofit中有如下的几个关键变量://用于缓存解析出来的方法

private

final

Map<Method,

ServiceMethod>

serviceMethodCache

=

new

LinkedHashMap<>();

//请求网络的OKHttp的工厂,默认是

OkHttpClient

private

final

okhttp3.Call.Factory

callFactory;

//baseurl

private

final

HttpUrl

baseUrl;

//请求网络得到的response的转换器的集合

默认会加入

BuiltInConverters

private

final

List<Converter.Factory>

converterFactories;

//把Call对象转换成其它类型

private

final

List<CallAdapter.Factory>

adapterFactories;

//用于执行回调

Android中默认是

MainThreadExecutor

private

final

Executor

callbackExecutor;

//是否需要立即解析接口中的方法

private

final

boolean

validateEagerly;再看一下Retrofit中的内部类Builder的builder方法:public

Retrofit

build()

{

if

(baseUrl

==

null)

{

throw

new

IllegalStateException("Base

URL

required.");

}

okhttp3.Call.Factory

callFactory

=

this.callFactory;

if

(callFactory

==

null)

{

//默认创建一个

OkHttpClient

callFactory

=

new

OkHttpClient();

}

Executor

callbackExecutor

=

this.callbackExecutor;

if

(callbackExecutor

==

null)

{

//Android

中返回的是

MainThreadExecutor

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);

}在创建Retrofit的时候,如果没有指定OkHttpClient,会创建一个默认的。如果没有指定

callbackExecutor,会返回平台默认的,在Android中是MainThreadExecutor,并利用这个构建一个

CallAdapter加入adapterFactories。create方法有了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();

@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.如果是Object中的方法,直接调用

if

(method.getDeclaringClass()

==

Object.class)

{

return

method.invoke(this,

args);

}

//为了兼容

Java8

平台,Android

中不会执行

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);

}

});create方法接受一个Class对象,也就是我们编写的接口,里面含有通过注解标识的请求网络的方法。注意return语句部分,这里调用了

Proxy.newProxyInstance

方法,这个很重要,因为用了动态代理模式。关于动态代理模式,可以参考这篇文章:/blogs/d...。简单的描述就是,Proxy.newProxyInstance

根据传进来的Class对象生成了一个实例A,也就是代理类。每当这个代理类A执行某个方法时,总是会调用

InvocationHandler(Proxy.newProxyInstance中的第三个参数)的invoke

方法,在这个方法中可以执行一些操作(这里是解析方法的注解参数等),通过这个方法真正的执行我们编写的接口中的网络请求。方法解析和类型转换下面具体看一下在invoke中解析网络请求方法的几行。首先是ServiceMethodserviceMethod=

loadServiceMethod(method);,其中loadServiceMethod代码如下: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;

}可以看出,这里是先到缓存中找,缓存中没有再去创建。这里创建了ServiceMethod对象。ServiceMethod用于把接口方法的调用转换成一个

HTTP请求。其实,在ServiceMethod中,会解析接口中方法的注解、参数等,它还有个toRequest方法,用于生成一个Request

对象。这个Request对象就是OkHttp中的Request,代表了一条网络请求(Retrofit实际上把真正请求网络的操作交给了OkHttp

执行)。下面是创建ServiceMethod的部分代码:public

ServiceMethod

build()

{

//获取

callAdapter

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

responseConverter

=

createResponseConverter();

for

(Annotation

annotation

:

methodAnnotations)

{

//解析注解

parseMethodAnnotation(annotation);

//省略了一些代码

...

}

}在得到ServiceMethod对象后,把它连同方法调用的相关参数传给了OkHttpCall对象,也就是这行代码:OkHttpCall

okHttpCall=newOkHttpCall<>(serviceMethod,args);。下面介绍

OkHttpCall,OkHttpCall继承于Call接口。Call是Retrofit

的基础接口,代表发送网络请求与响应调用,它包含下面几个接口方法:Response<T>execute()throwsIOException;//同步执行请求voidenqueue(Callback<T>callback);//异步执行请求,callback用于回调booleanisExecuted();//是否执行过voidcancel();//取消请求booleanisCanceled();//是否取消了Call<T>clone();//克隆一条请求Requestrequest();//获取原始的requestOkHttpCall是Call的一个实现类,它里面封装了OkHttp中的原生Call,在这个类里面实现了execute以及enqueue

等方法,其实是调用了OkHttp中原生Call的对应方法。接下来把OkHttpCall传给serviceMethod.callAdapter对象,这里的callAdapter又是什么?在上面创建

ServiceMethod的代码中有一行代码:callAdapter=createCallAdapter(),这里创建了

calladapter,在这个代码内部是根据方法的返回类型以及注解去寻找对应的CallAdapter,去哪里寻找?去Retrofit对象的

adapterFactories集合中找。当我们创建Retrofit的时候,可以调用addCallAdapter向adapterFactories

中添加CallAdapter。在前面的基本用法里面,我们并没有添加任何CallAdapter,但adapterFactories中默认会添加一个

ExecutorCallAdapterFactory,调用其get方法便可获得CallAdapter对象。那么CallAdapter是干嘛的呢?上面调用了adapt方法,它是为了把一个Call转换成另一种类型,比如当Retrofit和

RxJava结合使用的时候,接口中方法可以返回Observable<T>,这里相当于适配器模式。默认情况下得到的是一个Call

对象,它是ExecutorCallbackCall,代码如下: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);

}

};

}这个ExecutorCallbackCall接受一个callbackExecutor(Android中默认为

MainThreadExecutor,把返回的数据传回主线程)和一个call,也就是OkhttpCall。看下ExecutorCallbackCall

部分代码: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);

}

});

}

});

}在enqueue方法中,调用了OkHttpCall的enqueue,所以这里相当于静态的代理模式。OkHttpCall中的enqueue

其实又调用了原生的OkHttp中的enqueue,这里才真正发出了网络请求,部分代码如下:@Override

public

void

enqueue(final

Callback<T>

callback)

{

if

(callback

==

null)

throw

new

NullPointerException("callback

==

null");

//真正请求网络的

call

okhttp3.Call

call;

Throwable

failure;

synchronized

(this)

{

if

(executed)

throw

new

IllegalStateException("Already

executed.");

executed

=

true;

//省略了部分发代码

...

call

=

rawCal

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论