您的位置:首页 > 理论基础 > 计算机网络

深入解析开源项目之Retrofit(一)使用篇

2015-12-17 17:19 579 查看
珍惜作者劳动成果,如需转载,请注明出处。

http://blog.csdn.net/zhengzechuan91/article/details/50337883

Retrofit(Github地址)是square公司一套开源的http框架,简单易用,并且支持okhttp和RxJava,如果你不想为配置繁杂的http请求而写一套自己的网络请求框架,那么这套优雅的框架你不妨试试。

使用

先来说说这个框架的使用:

首先生成RestAdapter代理的接口RealService

RestAdapter adapter =   new RestAdapter.Builder()
.setClient()
.setEndpoint()
.setRequestInterceptor()
.setConverter()
.setLogLevel(LogLevel.FULL)
.build();

RealService real = adapter.create(RealService.class);


然后在接口RealService中定义:

同步

public interface RealService {
@GET("/info/")
String getString(@Query("id") String id)
}


如果是上面这种没有callback的同步方式,则需注意在非UI线程中调用。

String id = "1";
String info = real.getString(id);


异步

public interface RealService {
@GET("/info")
void getString(@Query("id") String id,
Callback<String> callback)
}


而如果参数中有callback的话,则可以直接在UI线程中调用,而返回值会通过callback返回。

String id = "1";
Callback<String> callback = new Callback() {
void success(String var1, Response var2);

void failure(RetrofitError var1);
}
real.getString(id, callback);


这样我们我获取到了API返回的数据,然后再根据这些数据做一些别的处理,使用是不是很简单呢?

上面我们看到参数、Url和请求方式都是通过注解的方式设置的,非常简单方便。

注解

首先来看一些注解的定义,这个在我们添加参数时还是很重要的:

作用于注解的注解

RestMethod

@Documented
//这个注解是用于注解上面的
@Target({ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface RestMethod {
//请求方式
String value();
//是否有body
boolean hasBody() default false;
}


作用于方法的注解

GET

@Documented
//这个注解是用于方法上的
@Target(METHOD)
@Retention(RUNTIME)
@RestMethod("GET")
public @interface GET {
//get请求方式,无body
String value();
}


POST

@Documented
//这个注解是用于方法上的
@Target(METHOD)
@Retention(RUNTIME)
@RestMethod(value = "POST", hasBody = true)
public @interface POST {
//post请求方式,有body
String value();
}


HEAD

@Documented
//这个注解是用于方法上的
@Target(METHOD)
@Retention(RUNTIME)
@RestMethod("HEAD")
public @interface HEAD {
//head请求,无body
String value();
}


PATCH

@Documented
//这个注解是用于方法上的
@Target(METHOD)
@Retention(RUNTIME)
@RestMethod(value = "PATCH", hasBody = true)
public @interface PATCH {
//patch请求,有body
String value();
}


PUT

@Documented
//这个注解是用于方法上的
@Target(METHOD)
@Retention(RUNTIME)
@RestMethod(value = "PUT", hasBody = true)
public @interface PUT {
//put请求,有body
String value();
}


FormUrlEncoded

@Documented
//这个注解是用于方法上的
@Target(METHOD)
@Retention(RUNTIME)
public @interface FormUrlEncoded {
//表单类型,参数使用@Field注解,application/x-www-form-
//urlencoded有值,并且在URI-decode前先会转为UTF-8
}


Headers

@Documented
//这个注解是用于方法上的
@Target(METHOD)
@Retention(RUNTIME)
public @interface Headers {
//head中添加参数
String[] value();
}


Multipart

@Documented
//这个注解是用于方法上的
@Target(METHOD)
d980

@Retention(RUNTIME)
public @interface Multipart {
//参数类型需为@Part注解
}


作用于参数的注解

Body

@Documented
//这个注解是用于参数中的
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Body {
//post/put方式参数标记
//如果参数被用@Body注解,则分为以下两种情况:
//1.这个参数实现了TypedOutput,则body会被重写为
//TypedOutput#writeTo();
//2.这个参数没有实现TypedOutput,则body会被RestAdapter
//的Converter序列化(serialized)
}


EncodedPath

@Documented
@Retention(RUNTIME)
//这个注解是用于参数中的
@Target(PARAMETER)
public @interface EncodedPath {
//这个注解标注的变量可以替换Path中的占位符,
//但不参与uri的decode,例如:
//@GET("/image/{id}")
//void example(@EncodedPath("id") int id, ..);
String value();
}


EncodedQuery

@Documented
//这个注解是用于参数中的
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface EncodedQuery {
//这个注解标注get请求单个参数,
//但不参与uri的decode
String value();
}


EncodedQueryMap

@Documented
//这个注解是用于参数中的
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface EncodedQueryMap {
//这个注解标注get请求Map参数,
//但不参与uri的decode
}


Path

@Documented
@Retention(RUNTIME)
//这个注解是用于参数中的
@Target(PARAMETER)
public @interface Path {
//这个注解标注的变量可以替换Path中的占位符
//参与uri的decode
String value();
}


Query

@Documented
//这个注解是用于参数中的
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Query {
//这个注解标注get请求单个参数,
//参与uri的decode
String value();
}


QueryMap

@Documented
//这个注解是用于参数中的
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface QueryMap {
//这个注解标注get请求Map参数,
//参与uri的decode
}


Field

@Documented
//这个注解是用于参数中的
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Field {
//标记表单类型,参数为单个变量
String value();
}


FieldMap

@Documented
//这个注解是用于参数中的
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface FieldMap {
//标记表单类型,参数为Map类型
}


Header

@Documented
@Retention(RUNTIME)
//这个注解是用于参数中的
@Target(PARAMETER)
public @interface Header {
//注解方式往head中添加参数
String value();
}


Part

@Documented
//这个注解是用于参数中的
@Target(PARAMETER)
@Retention(RUNTIME)
public @interface Part {
//Multipart的参数类型
//注解标记的变量分为以下3种情况:
//1.实现TypedOutput借口,直接使用
//2.String类型,直接使用
//3.其他类型会调用Converter#toBody()转换
String value();
}


Android参数注解选择

上面对用到的注解做了详细的介绍,总结下Android下注解的选择:

1.post请求:使用@Body标记参数

2.get请求:如果参数为为非Map类型,使用@Query标记参数

如果参数类型为Map类型,使用@QueryMap标记参数

3.上传文件/图片请求:使@Part标记参数

4.表单类型:如果参数类型为非Map类型,使用@Field标记参数

如果参数类型为Map类型,使用@FieldMap标记参数

5.如果方法的@GET或@POST中有占位符,使用@Path标记参数

基本常用的就这么多。

拦截器

我们在构造RestAdapter时,是可以设置自定义的拦截器,只需要实现RequestInterceptor接口。通过拦截器我们可以在请求Api之前向head、path、query中添加参数,来满足我们对一些公共参数的添加。

public class MyInterceptor implements RequestInterceptor {
@Override
public void intercept(RequestFacade request) {
//这里通过request往head、path、query中添加额外参数
request.addHeader("key1", "value1");
request.addPathParam("key2", "value2");
request.addQueryParam("key3", "value3");
}
}


我们发现这个回调返回的是一个RequestFacade类型的,我们看看

RequestFacade接口是怎么定义的:

public interface RequestFacade {
void addHeader(String var1, String var2);

void addPathParam(String var1, String var2);

void addEncodedPathParam(String var1, String var2);

void addQueryParam(String var1, String var2);

void addEncodedQueryParam(String var1, String var2);

RestMethodInfo getMethodInfo();
}


这个接口定义了向head、path、query中添加参数的接口,并且可以通过getMethodInfo()得到方法的注解信息。

Converter

框架默认实现的是到Gson的转换,如果我们的数据是别的Json解析方式或是xml解析方式,我们就需要自定义converter,先看下Converter接口的定义:

public interface Converter {
//从服务器读取数据(将输入流解析成POJO)
Object fromBody(TypedInput body, Type type)
throws ConversionException;

//向服务器发送数据(将POJO的字符串转换成流,写入输出流)
TypedOutput toBody(Object object);
}


我们看看TypedInput:

public interface TypedInput {
String mimeType();

long length();

InputStream in();
}


TypedInput给我们返回了mime类型、数据长度和输入流供我们解析。

public interface TypedOutput {
String fileName();

String mimeType();

long length();

void writeTo(OutputStream var1) throws IOException;
}


而TypedOutput则是给我们提供向服务器发送数据的输出流,我们将对象的(Json)字符串写入到输出流中。

而我们自定义Converter时,只需处理POJO和标准的TypedInput、TypedOutput的转换操作即可:

public class MyConverter implements Converter {

Object fromBody(TypedInput body, Type type) {
//从服务器读取数据(将输入流解析成POJO)
}

TypedOutput toBody(Object object) {
//向服务器发送数据(将POJO的字符串转换成流,
//写入输出流)
}
}


以上就是我们平常会在项目中用到的retrofit的全部内容,是不是很简单呢?使用简单,意味着框架为我们做了很多事情。下一篇博客我们将主要介绍retrofit的实现原理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息