前方高能--Retrofit

#Retrofit

A type-safe REST client for Android and Java


Android中非常有名的网络框架
官网 :https://square.github.io/retrofit/
参考项目: https://square.github.io/okhttp/
Android 示例项目: https://github.com/goodev/RetrofitDemo


Retrofit vs Volley
https://instructure.github.io/blog/2013/12/09/volley-vs-retrofit/
提取一张图片
这里写图片描述

1
2
3
4
5
//API
public interface ApiService {
@GET("/jobs")
public void getJobs(Callback<Data> callback);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
//RestClient
public class RestClient {

private static final String BASE_URL = "https://yourapi.host.com";
private ApiService apiService;

public RestClient() {
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(new ItemTypeAdapterFactory())
.setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
.create();

RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(BASE_URL)
.setConverter(new GsonConverter(gson))
.setRequestInterceptor(new SessionRequestInterceptor())
.setClient(new OkClient(MySSLTrust.getUnsafeOkHttpClient()))
.build();

apiService = restAdapter.create(ApiService.class);
}

public ApiService getApiService() {
return apiService;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
//MySSLTrust 的SSL信任
public class MySSLTrust {
public static OkHttpClient getUnsafeOkHttpClient() {
try {
// Create a trust manager that does not validate certificate chains
final TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
@Override
public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}

@Override
public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
}

@Override
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
}
};

// Install the all-trusting trust manager
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
// Create an ssl socket factory with our all-trusting manager
final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

OkHttpClient okHttpClient = new OkHttpClient();
okHttpClient.setSslSocketFactory(sslSocketFactory);
okHttpClient.setHostnameVerifier(new HostnameVerifier() {
@Override
public boolean verify(String hostname, SSLSession session) {
return true;
}
});

return okHttpClient;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}


/**
* add Headers fro every request
* Created by Hanks on 2015/5/18.
*/
public class SessionRequestInterceptor implements RequestInterceptor {
@Override
public void intercept(RequestFacade request) {
/*request.addHeader("Accept", "application/json;versions=1");
if(isUserLoggedIn()){
request.addHeader("Authorization",getToken());
}*/
request.addHeader("Authorization","huhu=");
}
}

官网的几个例子:
API Declaration

Annotations on the interface methods and its parameters indicate how a request will be handled.

REQUEST METHOD

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.

1
@GET("/users/list")

You can also specify query parameters in the URL.

1
@GET("/users/list?sort=desc")

URL MANIPULATION

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 groupList(@Path(“id”) int groupId);
Query parameters can also be added.

1
2
@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.

1
@GET("/group/{id}/users")

List groupList(@Path(“id”) int groupId, @QueryMap Map<String, String> options);
REQUEST BODY

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 cb);
The object will also be converted using the RestAdapter’s converter.

FORM ENCODED AND MULTIPART

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.

HEADER MANIPULATION

You can set static headers for a method using the @Headers annotation.

1
2
3
4
5
6
7
@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"
})
1
@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.

1
2
@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 a RequestInterceptor that will add a User-Agent header to every request.

1
2
3
4
5
6
7
8
9
10
11
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();

SYNCHRONOUS VS. ASYNCHRONOUS VS. OBSERVABLE

Methods can be declared for either synchronous or asynchronous execution.

A method with a return type will be executed synchronously.

1
@GET("/user/{id}/photo")

Photo getUserPhoto(@Path(“id”) int id);
Asynchronous execution requires the last parameter of the method be a Callback.

1
@GET("/user/{id}/photo")

void getUserPhoto(@Path(“id”) int id, Callback 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

1
@GET("/user/{id}/photo")

Observable 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.

RESPONSE OBJECT TYPE

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.

1
2
@GET("/users/list")
List<User> userList();
1
2
@GET("/users/list")
void userList(Callback<List<User>> cb);
1
2
@GET("/users/list")
Observable<List<User>> userList();

For access to the raw HTTP response use the Response type.

1
2
@GET("/users/list")
Response userList();
1
2
@GET("/users/list")
void userList(Callback<Response> cb);
1
2
@GET("/users/list")
Observable<Response> userList();