@wangwangheng
2015-04-12T07:46:36.000000Z
字数 5944
阅读 3558
第三方&开源
REST API
到一个Java接口:
public interface GitHubService {
@GET("/users/{user}/repos")
List<Repo> listRepos(@Path("user") String user);
}
RestAdapter
生成GitHubService
接口的一个实现:
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.build();
GitHubService service = restAdapter.create(GitHubService.class);
GitHubService
的一个方法都会对远程Web服务器发出一个HTTP请求:
List<Repo> repos = service.listRepos("octocat");
GET
,POST
,PUT
,DELETE
,HEAD
。资源的相对URL被指定在这个注解中。
@GET("/users/list")
@GET("/users/list?sort=desc")
{
和}
包围的字母数字字符串。对应的参数必须在@Path
注解中使用相同的字符串:
@GET("/group/{id}/users")
List<User> groupList(@Path("id") int groupId);
@GET("/group/{id}/users")
List<User> groupList(@Path("id") int groupId, @Query("sort") String sort);
@GET("/group/{id}/users")
List<User> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
@Body
注解指定为HTTP请求体:
@POST("/users/new")
void createUser(@Body User user, Callback<User> cb);
RestAdapter
的转换器转换。@FormUrlEncoded
注解存在于方法上的时候,数据将以表单格式发送。每个键 -值对
的键是 @Field
的value
,值是@Field
所注解的参数的值:
@FormUrlEncoded
@POST("/user/edit")
User updateUser(@Field("first_name") String first, @Field("last_name") String last);
@Multipart
注解一个方法的时候,数据将以Multipart的格式发送,使用@Part
来注解每一个Part:
@Multipart
@PUT("/user/photo")
User updateUser(@Part("photo") TypedFile photo, @Part("description") TypedString description);
RestAdapter
的转换器或者它们实现TypeOutput
去处理它们自己的序列化@Header
注解来设置静态的header信息:
@Headers("Cache-Control: max-age=640000")
@GET("/widget/list")
List<Widget> widgetList();
@Headers({
"Accept: application/vnd.github.v3.full+json",
"User-Agent: Retrofit-Sample-App"
})
@GET("/users/{username}")
User getUser(@Path("username") String username);
需要注意的是Header不会相互覆盖。所有的header将以相同的名称包含在请求里面。
请求的Header可以使用@Header
注解进行动态的更新。一个符合条件的参数必须使用@Header
来提供,如果你提供的参数值为null,则这个Header将被忽略,否则将会使用这个参数的toString()
函数的调用结果:
@GET("/user")
void getUser(@Header("Authorization") String authorization, Callback<User> callback)
RequestInterceptor
,下面的代码创建一个RequestInterceptor
为每一个请求添加一个User-Agent
的请求头:
RequestInterceptor requestInterceptor = new RequestInterceptor() {
@Override
public void intercept(RequestFacade request) {
request.addHeader("User-Agent", "Retrofit-Sample-App");
}
};
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.setRequestInterceptor(requestInterceptor)
.build();
方法能够被声明为同步或者异步执行。
@GET("/user/{id}/photo")
Photo getUserPhoto(@Path("id") int id);
Callback
@GET("/user/{id}/photo")
void getUserPhoto(@Path("id") int id, Callback<Photo> cb);
在Android中,callback在主线程中执行。对于桌面应用程序callback将会在执行Http请求的线程中执行。
rx.Observable
:
@GET("/user/{id}/photo")
Observable<Photo> getUserPhoto(@Path("id") int id);
Observable请求是订阅异步请求并且在执行HTTP请求的相同线程上观察,调用在不同的线程的(例如Android的主线程)observeOn(Scheduler)方法对返回的Observable进行观察。
RestAdapter
的转换器会自动把HTTP的响应数据转换为指定的类型(默认是JSON),想要的类型通过方法的返回值类型,Callback的泛型类型或者Observable的泛型类型来指定:
@GET("/users/list")
List<User> userList();
@GET("/users/list")
void userList(Callback<List<User>> cb);
@GET("/users/list")
Observable<List<User>> userList();
Response
类型来访问HTTP请求的原生响应结果:
@GET("/users/list")
Response userList();
@GET("/users/list")
void userList(Callback<Response> cb);
@GET("/users/list")
Observable<Response> userList();
RestAdapter
是把你的API接口转换为可调用的方法的类(实际上是通过动态代理来生成具体的请求类的对象),默认情况下Retrofit为合适的平台提供合适的默认配置,但是它也允许自定义配置。
Retrofit默认使用Gson来转换请求参数并把服务端返回的原生数据转换为你指定的类型。如果你想指定不同的Gson的默认行为(如命名策略,数据类型,自定义类型),可以在build一个RestAdapter
的时候指定一个包含你所期望行为新的Gson的实例,可以参考Gson文档来了解自定义Gson行为。
下面的代码创建一个把所有字段从用下划线分割的小写字母转换为驼峰命名法。它也为Date
类注册了一个类型的适配器。这个DateTypeAdapter
将会在Gson解析日期类型的时候使用。
该gson
实例作为GsonConverter
参数,这是一个用于转换类型的包装类。
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
.registerTypeAdapter(Date.class, new DateTypeAdapter())
.create();
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.setConverter(new GsonConverter(gson))
.build();
GitHubService service = restAdapter.create(GitHubService.class);
GithubServic
的实现将返回数据将被设置到RestAdapter
的GSON对象转换为需要的对象。除了JSON,Retrofit也可以配置其他的内容格式,Retrofit提供了可选的XML转换器(使用Sample -- 一个高性能的XML序列化和配置框架)和协议缓冲池(使用protobuf 或者 Wire).请查看retrofit-converters目录查看所有的转换器列表。
下面的代码展示了怎样使用SimpleXMLConverter
与使用XML的API通讯:
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.soundcloud.com")
.setConverter(new SimpleXMLConverter())
.build();
SoundCloudService service = restAdapter.create(SoundCloudService.class);
入股哦你需要使用一个Retrofit不支持的内容格式与API通讯(如YAML,txt,自定义格式)或者或者你想使用一个不同而库来实现现有格式,你可以轻松的创建你自己的转换器。创建一个类并且实现Converter
接口并且在创建适配器的时候传递一个实例。
如果你需要自定义错误处理的请求,您可以提供自己的ErrorHandler
。下面的代码展示了怎样在服务器返回401状态码的时候抛出一个自定义的异常:
class MyErrorHandler implements ErrorHandler {
@Override
public Throwable handleError(RetrofitError cause) {
Response r = cause.getResponse();
if (r != null && r.getStatus() == 401) {
return new UnauthorizedException(cause);
}
return cause;
}
}
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.setErrorHandler(new MyErrorHandler())
.build();
注意,如果返回的异常是被封闭的,它必须被定义在接口方法中。建议您通过我们提供的RetrofitError的错误原因抛出新的异常。
如果你需要详细查看请求和响应,你可以很轻松地添加日志级别到RestAdapter
中。可能的日志级别是:BASIC
,FULL
,HEADERS
和NONE
.
下面的代码展示了如何记录Header,Boady,和元数据请求和响应的一个完整的日志级别:
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint("https://api.github.com")
.build();
这个日志能够在RestAdapter
的任何生命周期的时间点通过调用.setLogLevel()
方法添加或者改变不同的日志级别的值。