Retrofit turns your REST API into a Java interface.
public interface GitHubService { @GET("/users/{user}/repos") List<Repo> listRepos(@Path("user") String user); }
The RestAdapter
class generates an implementation of the GitHubService
interface.
RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://api.github.com") .build(); GitHubService service = restAdapter.create(GitHubService.class);
Each call on the generated GitHubService
makes an HTTP request to the remote webserver.
List<Repo> repos = service.listRepos("octocat");
Use annotations to describe the HTTP request:
Annotations on the interface methods and its parameters indicate how a request will be handled.
Every method must have an HTTP annotation that provides the request method and relative URL. There are five built-in annotations: GET
, POST
, PUT
, DELETE
, and HEAD
. The relative URL of the resource is specified in the annotation.
@GET("/users/list")
You can also specify query parameters in the URL.
@GET("/users/list?sort=desc")
A request URL can be updated dynamically using replacement blocks and parameters on the method. A replacement block is an alphanumeric string surrounded by {
and }
. A corresponding parameter must be annotated with @Path
using the same string.
@GET("/group/{id}/users") List<User> groupList(@Path("id") int groupId);
Query parameters can also be added.
@GET("/group/{id}/users") List<User> groupList(@Path("id") int groupId, @Query("sort") String sort);
For complex query parameter combinations a Map
can be used.
@GET("/group/{id}/users") List<User> groupList(@Path("id") int groupId, @QueryMap Map<String, String> options);
An object can be specified for use as an HTTP request body with the @Body
annotation.
@POST("/users/new") void createUser(@Body User user, Callback<User> cb);
The object will also be converted using the RestAdapter
's converter.
Methods can also be declared to send form-encoded and multipart data.
Form-encoded data is sent when @FormUrlEncoded
is present on the method. Each key-value pair is annotated with @Field
containing the name and the object providing the value.
@FormUrlEncoded @POST("/user/edit") User updateUser(@Field("first_name") String first, @Field("last_name") String last);
Multipart requests are used when @Multipart
is present on the method. Parts are declared using the @Part
annotation.
@Multipart @PUT("/user/photo") User updateUser(@Part("photo") TypedFile photo, @Part("description") TypedString description);
Multipart parts use the RestAdapter
's converter or they can implement TypedOutput
to handle their own serialization.
You can set static headers for a method using the @Headers
annotation.
@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);
Note that headers do not overwrite each other. All headers with the same name will be included in the request.
A request Header can be updated dynamically using the @Header
annotation. A corresponding parameter must be provided to the@Header
. If the value is null, the header will be omitted. Otherwise, toString
will be called on the value, and the result used.
@GET("/user") void getUser(@Header("Authorization") String authorization, Callback<User> callback)
Headers that need to be added to every request can be specified using a RequestInterceptor
. The following code creates aRequestInterceptor
that will add a User-Agent
header to every request.
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();
Methods can be declared for either synchronous or asynchronous execution.
A method with a return type will be executed synchronously.
@GET("/user/{id}/photo") Photo getUserPhoto(@Path("id") int id);
Asynchronous execution requires the last parameter of the method be a Callback
.
@GET("/user/{id}/photo") void getUserPhoto(@Path("id") int id, Callback<Photo> cb);
On Android, callbacks will be executed on the main thread. For desktop applications callbacks will happen on the same thread that executed the HTTP request.
Retrofit also integrates RxJava to support methods with a return type of rx.Observable
@GET("/user/{id}/photo") Observable<Photo> getUserPhoto(@Path("id") int id);
Observable requests are subscribed asynchronously and observed on the same thread that executed the HTTP request. To observe on a different thread (e.g. Android's main thread) call observeOn(Scheduler)
on the returned Observable
.
HTTP responses are automatically converted to a specified type using the RestAdapter
's converter which defaults to JSON. The desired type is declared as the method return type or using the Callback
or Observable
.
@GET("/users/list") List<User> userList(); @GET("/users/list") void userList(Callback<List<User>> cb); @GET("/users/list") Observable<List<User>> userList();
For access to the raw HTTP response use the Response
type.
@GET("/users/list") Response userList(); @GET("/users/list") void userList(Callback<Response> cb); @GET("/users/list") Observable<Response> userList();
RestAdapter
is the class through which your API interfaces are turned into callable objects. By default, Retrofit will give you sane defaults for your platform but it allows for customization.
Retrofit uses Gson by default to convert HTTP bodies to and from JSON. If you want to specify behavior that is different from Gson's defaults (e.g. naming policies, date formats, custom types), provide a new Gson
instance with your desired behavior when building a RestAdapter
. Refer to the Gson documentation for more details on customization.
The following code creates a new Gson
instance that will convert all fields from lower case with underscores to camel case and vice versa. It also registers a type adapter for the Date
class. This DateTypeAdapter
will be used anytime Gson encounters a Date
field.
The gson
instance is passed as a parameter to GsonConverter
, which is a wrapper class for converting types.
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);
Each call on the generated GithubService
will return objects converted using the Gson implementation provided to theRestAdapter
.
In addition to JSON, Retrofit can be configured to use other content formats. Retrofit provides alternate converters for XML (usingSimple) and Protocol Buffers (using protobuf or Wire). Please see the retrofit-converters directory for the full listing of converters.
The following code shows how to use SimpleXMLConverter
to communicate with an API that uses XML
RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://api.soundcloud.com") .setConverter(new SimpleXMLConverter()) .build(); SoundCloudService service = restAdapter.create(SoundCloudService.class);
If you need to communicate with an API that uses a content-format that Retrofit does not support out of the box (e.g. YAML, txt, custom format) or you wish to use a different library to implement an existing format, you can easily create your own converter. Create a class that implements the Converter
interface and pass in an instance when building your adapter.
If you need custom error handling for requests, you may provide your own ErrorHandler
. The following code shows how to throw a custom exception when a response returns a HTTP 401 status code
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();
Note that if the return exception is checked, it must be declared on the interface method. It is recommended that you pass the supplied RetrofitError
as the cause to any new exceptions you throw.
If you need to take a closer look at the requests and responses you can easily add logging levels to the RestAdapter
with theLogLevel
property. The possible logging levels are BASIC
, FULL
, HEADERS
, and NONE
.
The following code shows the addition of a full log level which will log the headers, body, and metadata for both requests and responses.
RestAdapter restAdapter = new RestAdapter.Builder() .setLogLevel(RestAdapter.LogLevel.FULL) .setEndpoint("https://api.github.com") .build();
This logging can be added or changed at any point in the RestAdapter
's lifecycle by calling the same .setLogLevel()
method and supplying a different LogLevel
value.
The source code to the Retrofit, its samples, and this website is available on GitHub.
<dependency>
<groupId>com.squareup.retrofit</groupId>
<artifactId>retrofit</artifactId>
<version>(insert latest version)</version>
</dependency>
compile 'com.squareup.retrofit:retrofit:(insert latest version)'
Retrofit requires at minimum Java 6 or Android 2.3.
When using Retrofit together with OkHttp, OkHttp (version 1.6.0 or newer) and OkHttp-UrlConnection are now required.
<dependency> <groupId>com.squareup.okhttp</groupId> <artifactId>okhttp</artifactId> <version>2.0.0</version> </dependency> <dependency> <groupId>com.squareup.okhttp</groupId> <artifactId>okhttp-urlconnection</artifactId> <version>2.0.0</version> </dependency>
compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0' compile 'com.squareup.okhttp:okhttp:2.0.0'
If you would like to contribute code you can do so through GitHub by forking the repository and sending a pull request.
When submitting code, please make every effort to follow existing conventions and style in order to keep the code as readable as possible. Please also make sure your code compiles by running mvn clean verify
.
Before your code can be accepted into the project you must also sign the Individual Contributor License Agreement (CLA).
Copyright 2013 Square, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
评论