Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Retrofit
Search
Adrien Couque
January 22, 2015
Technology
130
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Retrofit
Adrien Couque
January 22, 2015
More Decks by Adrien Couque
See All by Adrien Couque
A roadmap to psychohistory
acq
0
120
ML Session n°8
acq
0
64
ML Session n°7
acq
0
26
ML Session n°6
acq
0
45
ML Session n°5
acq
0
65
ML Session n°4
acq
0
43
ML Session n°3
acq
0
110
ML Session n°2
acq
1
100
ML Session n°1
acq
0
97
Other Decks in Technology
See All in Technology
Claude Codeを「使うほど育つ」AI秘書にするノウハウ
minorun365
PRO
32
28k
10Xに技術的負債をもたらした「2つの境界の歪み」その構造と解消への営み
10xinc
0
2.1k
Claude in Chrome 入門 / Introduction to Claude in Chrome
cielo1985
0
870
2026_devsumi_ozono.pdf
o3
3
530
EventBridge に「合流」はない ― サーバーレスのワークフローを育てるということ / No Join in EventBridge
yusukeshimizu
2
290
今話題のAI「Jev」って何? 宇宙最速で学ぶ会
minorun365
PRO
30
17k
aws-iot-platform-architecture-use-cases.pdf
ma2shita
0
390
時うどん〜Socket.getifaddrsで学ぶネットワーク編 / Tokiudon: The Socket.getifaddrs Edition
coe401_
3
150
アクセスキーこわい やめかたと漏らさない工夫
sassssan68
1
500
SREへの勘違いに気づいた後の話
tomodakengo
0
110
AIで社員の自主発信に広報目線を組み込む
_mossann_t
0
130
「守り」で活用するオンデバイスLLM 〜写ってはいけないを総力戦で防ぐ〜 / iOSDC Japan 2026
nakamuuu
0
180
Featured
See All Featured
Designing for Performance
lara
611
70k
A Modern Web Designer's Workflow
chriscoyier
699
190k
Accessibility Awareness
sabderemane
1
210
<Decoding/> the Language of Devs - We Love SEO 2024
nikkihalliwell
1
330
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
1
530
Deep Space Network (abreviated)
tonyrice
0
310
Design of three-dimensional binary manipulators for pick-and-place task avoiding obstacles (IECON2024)
konakalab
0
600
エンジニアに許された特別な時間の終わり
watany
109
250k
Between Models and Reality
mayunak
4
460
How to Think Like a Performance Engineer
csswizardry
28
2.8k
How to Get Subject Matter Experts Bought In and Actively Contributing to SEO & PR Initiatives.
livdayseo
0
200
How STYLIGHT went responsive
nonsquared
100
6.3k
Transcript
an introduction to Retrofit Applidium
Retrofit 2015 • Old way RestClient.get(this, App.getWebServiceBaseURL() + "/associate/annual-salaries.json", new
JacksonHttpResponseHandler<List<AnnualSalary>>( this, new TypeReference<List<AnnualSalary>>() {} ) { @Override public void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, List<AnnualSalary> response) { // … } @Override public void onRequestFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, List<AnnualSalary> errorResponse) { // … } });
Retrofit 2015 • Old way: URL RestClient.get(this, App.getWebServiceBaseURL() + "/associate/annual-salaries.json",
new JacksonHttpResponseHandler<List<AnnualSalary>>( this, new TypeReference<List<AnnualSalary>>() {} ) { @Override public void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, List<AnnualSalary> response) { // TODO } @Override public void onRequestFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, List<AnnualSalary> errorResponse) { // TODO } });
Retrofit 2015 • Old way: return type RestClient.get(this, App.getWebServiceBaseURL() +
"/associate/annual-salaries.json", new JacksonHttpResponseHandler<List<AnnualSalary>>( this, new TypeReference<List<AnnualSalary>>() {} ) { @Override public void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, List<AnnualSalary> response) { // TODO } @Override public void onRequestFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, List<AnnualSalary> errorResponse) { // TODO } });
Retrofit 2015 • Old way: success RestClient.get(this, App.getWebServiceBaseURL() + "/associate/annual-salaries.json",
new JacksonHttpResponseHandler<List<AnnualSalary>>( this, new TypeReference<List<AnnualSalary>>() {} ) { @Override public void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, List<AnnualSalary> response) { // TODO } @Override public void onRequestFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, List<AnnualSalary> errorResponse) { // TODO } });
Retrofit 2015 • Old way: failure RestClient.get(this, App.getWebServiceBaseURL() + "/associate/annual-salaries.json",
new JacksonHttpResponseHandler<List<AnnualSalary>>( this, new TypeReference<List<AnnualSalary>>() {} ) { @Override public void onSuccess(int statusCode, Header[] headers, String rawJsonResponse, List<AnnualSalary> response) { // TODO } @Override public void onRequestFailure(int statusCode, Header[] headers, Throwable throwable, String rawJsonData, List<AnnualSalary> errorResponse) { // TODO } });
Retrofit 2015 • New way @GET("/associate/annual-salaries.json") List<AnnualSalary> getAnnualSalaries();
Retrofit 2015 • Building the API Manager public class ApiManager
{ public interface ApiManagerService { @GET("/associate/annual-salaries.json") List<AnnualSalary> getAnnualSalaries(); } private static ApiManagerService sApiManagerService; public static ApiManagerService getApiManager() { if (sApiManagerService == null) { RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWebServiceBaseURL()) .build(); sApiManagerService = adapter.create(ApiManagerService.class); } return sApiManagerService; } }
Retrofit 2015 • Building the API Manager public class ApiManager
{ public interface ApiManagerService { @GET("/associate/annual-salaries.json") List<AnnualSalary> getAnnualSalaries(); } private static ApiManagerService sApiManagerService; public static ApiManagerService getApiManager() { if (sApiManagerService == null) { RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWebServiceBaseURL()) .build(); sApiManagerService = adapter.create(ApiManagerService.class); } return sApiManagerService; } }
Retrofit 2015 • Building the API Manager public class ApiManager
{ public interface ApiManagerService { @GET("/associate/annual-salaries.json") List<AnnualSalary> getAnnualSalaries(); } private static ApiManagerService sApiManagerService; public static ApiManagerService getApiManager() { if (sApiManagerService == null) { RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWebServiceBaseURL()) .build(); sApiManagerService = adapter.create(ApiManagerService.class); } return sApiManagerService; } }
Retrofit 2015 • Building the API Manager public class ApiManager
{ public interface ApiManagerService { @GET("/associate/annual-salaries.json") List<AnnualSalary> getAnnualSalaries(); } private static ApiManagerService sApiManagerService; public static ApiManagerService getApiManager() { if (sApiManagerService == null) { RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWebServiceBaseURL()) .build(); sApiManagerService = adapter.create(ApiManagerService.class); } return sApiManagerService; } }
Retrofit 2015 • Building the API Manager public class ApiManager
{ public interface ApiManagerService { @GET("/associate/annual-salaries.json") List<AnnualSalary> getAnnualSalaries(); } private static ApiManagerService sApiManagerService; public static ApiManagerService getApiManager() { if (sApiManagerService == null) { RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWebServiceBaseURL()) .build(); sApiManagerService = adapter.create(ApiManagerService.class); } return sApiManagerService; } }
Retrofit 2015 • HTTP Verbs @GET(“/foo/bar”) @POST(“/foo/bar”) @PUT(“/foo/bar”) @PATCH(“/foo/bar”) @DELETE(“/foo/bar”)
@HEAD(“/foo/bar”)
Retrofit 2015 • Synchronous vs Asynchronous @GET("/associate/annual-salaries.json") List<AnnualSalary> getAnnualSalaries();
@GET("/associate/annual-salaries.json") void getAnnualSalaries(Callback<List<AnnualSalary>> callback);
Retrofit 2015 • Path @GET("/group/{id}/users") List<User> groupList(@Path("id") int groupId);
Retrofit 2015 • Query @GET("/users") List<User> groupList(@Query("sort") String sort);
@GET("/users") List<User> groupList(@QueryMap Map<String, String> options);
Retrofit 2015 • Body @POST("/users/new") User createUser(@Body User user);
Retrofit 2015 • Form encoding @FormUrlEncoded @POST("/user/edit") User updateUser(@Field("first_name") String
first, @Field("last_name") String last);
Retrofit 2015 • Multipart @Multipart @PUT("/user/photo") User updateUser(@Part("photo") TypedFile photo,
@Part("description") TypedString description);
Retrofit 2015 • Headers @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);
Retrofit 2015 • Headers @GET("/user") User getUser(@Header("Authorization") String authorization);
Retrofit 2015 • Headers 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(); sApiManagerService = restAdapter.create(ApiManagerService.class);
Retrofit 2015 • RequestInterceptor RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWSUrl())
.setRequestInterceptor(new RequestInterceptor() { @Override public void intercept(RequestFacade request) { request.addQueryParam("u", getUserEmail()); request.addQueryParam("t", getUserAuthToken()); } }).build(); sApiManagerServicePull = adapter.create(ApiManagerServicePull.class);
Retrofit 2015 • RequestInterceptor RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWSUrl())
.setRequestInterceptor(new RequestInterceptor() { @Override public void intercept(RequestFacade request) { request.addQueryParam("u", getUserEmail()); request.addQueryParam("t", getUserAuthToken()); } }).build(); sApiManagerServicePull = adapter.create(ApiManagerServicePull.class);
Retrofit 2015 • RequestInterceptor interface RequestFacade { void addHeader(String
name, String value); void addPathParam(String name, String value); void addEncodedPathParam(String name, String value); void addQueryParam(String name, String value); void addEncodedQueryParam(String name, String value); }
Retrofit 2015 • Error handling public abstract class RestCallback<T> implements
Callback<T> { public abstract void failure(RestError restError); @Override public void failure(RetrofitError error) { RestError restError = (RestError) error.getBodyAs(RestError.class); if (restError != null) { failure(restError); } else { failure(new RestError(error.getMessage())); } } } public class RestError { private String errorMessage; public RestError(String errorMessage) { this.errorMessage = errorMessage; } } { "error_message": “User not found" }
Retrofit 2015 • Twitter API public interface TwitterService { @Headers({
"Content-Type: application/x-www-form-urlencoded;charset=UTF-8"}) @POST("/oauth2/token") Authenticated authorizeUser( @Header("Authorization") String authorization, @Header("Content-Length") String bodyLength, @Body TypedString grantType); @Headers({ "Content-Type: application/json" }) @GET("/1.1/lists/statuses.json") List<Tweet> getTwitterStream( @Header("Authorization") String authorization, @Query("slug") String slug, @Query("owner_screen_name") String screenName); }
Retrofit 2015 • Converters ObjectMapper mapper = new ObjectMapper();
RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWSUrl()) .setConverter(new JacksonConverter(mapper)) .build(); sApiManagerService = adapter.create(ApiManagerService.class); // build.gradle: compile 'com.squareup.retrofit:converter-jackson:1.9.0'
Retrofit 2015 • Jackson: fields ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWSUrl()) .setConverter(new JacksonConverter(mapper)) .build(); sApiManagerService = adapter.create(ApiManagerService.class);
Retrofit 2015 • Jackson: property names ObjectMapper mapper = new
ObjectMapper(); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); mapper.setPropertyNamingStrategy( PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWSUrl()) .setConverter(new JacksonConverter(mapper)) .build(); sApiManagerService = adapter.create(ApiManagerService.class);
Retrofit 2015 • Jackson: null values ObjectMapper mapper = new
ObjectMapper(); mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); mapper.setPropertyNamingStrategy( PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWSUrl()) .setConverter(new JacksonConverter(mapper)) .build(); sApiManagerService = adapter.create(ApiManagerService.class);
Retrofit 2015 • Jackson: dates ObjectMapper mapper = new ObjectMapper();
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY); mapper.setPropertyNamingStrategy( PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")); RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWSUrl()) .setConverter(new JacksonConverter(mapper)) .build(); sApiManagerService = adapter.create(ApiManagerService.class);
Retrofit 2015 • Jackson ObjectMapper mapper = new ObjectMapper(); mapper.setVisibility(PropertyAccessor.FIELD,
JsonAutoDetect.Visibility.ANY); mapper.setPropertyNamingStrategy( PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES); mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")); if (!BuildConfig.DEBUG) { mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); } RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWSUrl()) .setConverter(new JacksonConverter(mapper)) .build(); sApiManagerService = adapter.create(ApiManagerService.class);
Retrofit 2015 • Jackson: property names @JsonProperty("id") protected String uuid;
@JsonIgnore protected String uuid; @JsonProperty public String getId() { return uuid; }
Retrofit 2015 • Jackson: property names @JsonProperty("id") protected String uuid;
@JsonIgnore protected String uuid; @JsonProperty public String getId() { return uuid; }
Retrofit 2015 • Jackson: properties @JsonIgnoreProperties({“original_id”, “updated_at”}) public class Site
extends ManagedObject { } @JsonProperty("updated_at") public void setUpdatedAt(Date updatedAt) { this.updatedAt = updatedAt; }
Retrofit 2015 • Jackson: properties @JsonIgnoreProperties({“original_id”, “updated_at”}) public class Site
extends ManagedObject { } @JsonProperty("updated_at") public void setUpdatedAt(Date updatedAt) { this.updatedAt = updatedAt; }
Retrofit 2015 • Multiple converters public static ApiManagerService getApiManager() {
if (sApiManagerService == null) { RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWSUrl()) .setConverter(new JacksonConverter(mapper)) .build(); sApiManagerService = adapter.create(ApiManagerService.class); } return sApiManagerService; } public static CanalApiManagerService getCanalApiManager() { if (sCanalApiManagerService == null) { RestAdapter adapter = new RestAdapter.Builder() .setEndpoint("https://secure-webtv.canal-plus.com") .setConverter(new SimpleXMLConverter()).build(); sCanalApiManagerService = adapter.create(CanalApiManagerService.class); } return sCanalApiManagerService;
Retrofit 2015 • Multiple converters public static ApiManagerService getApiManager() {
if (sApiManagerService == null) { RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWSUrl()) .setConverter(new JacksonConverter(mapper)) .build(); sApiManagerService = adapter.create(ApiManagerService.class); } return sApiManagerService; } public static CanalApiManagerService getCanalApiManager() { if (sCanalApiManagerService == null) { RestAdapter adapter = new RestAdapter.Builder() .setEndpoint("https://secure-webtv.canal-plus.com") .setConverter(new SimpleXMLConverter()).build(); sCanalApiManagerService = adapter.create(CanalApiManagerService.class); } return sCanalApiManagerService; }
Retrofit 2015 • Multiple converters public static ApiManagerService getApiManager() {
if (sApiManagerService == null) { RestAdapter adapter = new RestAdapter.Builder() .setEndpoint(App.getWSUrl()) .setConverter(new JacksonConverter(mapper)) .build(); sApiManagerService = adapter.create(ApiManagerService.class); } return sApiManagerService; } public static CanalApiManagerService getCanalApiManager() { if (sCanalApiManagerService == null) { RestAdapter adapter = new RestAdapter.Builder() .setEndpoint("https://secure-webtv.canal-plus.com") .setConverter(new SimpleXMLConverter()).build(); sCanalApiManagerService = adapter.create(CanalApiManagerService.class); } return sCanalApiManagerService;
Retrofit 2015 • Logs RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint(“https://api.github.com")
.build(); if (BuildConfig.DEBUG) { restAdapter.setLogLevel(RestAdapter.LogLevel.FULL); } public enum LogLevel { NONE, BASIC, HEADERS, HEADERS_AND_ARGS, FULL; }
Retrofit 2015 • Logs D/Retrofit﹕ ---> HTTP GET https://deco101.tortuba.com/api/v1/trips.json?since=Tue +Jan+20+21%3A29%3A54+GMT%2B01%3A00+2015&u=adrien.couque
%40applidium.com&t=VjtC7zZxqp5thJpvShUb D/Retrofit﹕ ---> END HTTP (no body) D/Retrofit﹕ <--- HTTP 200 https://deco101.tortuba.com/api/v1/trips.json?since=Tue +Jan+20+21%3A29%3A54+GMT%2B01%3A00+2015&u=adrien.couque %40applidium.com&t=VjtC7zZxqp5thJpvShUb (810ms) D/Retrofit﹕ : HTTP/1.1 200 OK D/Retrofit﹕ Cache-Control: max-age=0, private, must-revalidate D/Retrofit﹕ CF-RAY: 1ac4d9b1275b1509-CDG D/Retrofit﹕ Connection: keep-alive D/Retrofit﹕ Content-Type: application/json; charset=utf-8 D/Retrofit﹕ Date: Wed, 21 Jan 2015 16:22:24 GMT D/Retrofit﹕ Server: cloudflare-nginx D/Retrofit﹕ Set-Cookie: __cfduid=d87f09effa9f48e43b0bc401ec5d0d7bc1421857344; expires=Thu, 21-Jan-16 16:22:24 GMT; path=/; domain=.tortuba.com; HttpOnly D/Retrofit﹕ Status: 200 OK D/Retrofit﹕ Strict-Transport-Security: max-age=31536000 D/Retrofit﹕ Transfer-Encoding: chunked D/Retrofit﹕ X-Android-Received-Millis: 1421857343782 D/Retrofit﹕ X-Android-Response-Source: NETWORK 200 D/Retrofit﹕ X-Android-Sent-Millis: 1421857343007 D/Retrofit﹕ X-Frame-Options: SAMEORIGIN D/Retrofit﹕ X-Request-Id: 1c9e3619-99d7-4fa8-a7e1-a2bcf62b0058 D/Retrofit﹕ X-Runtime: 0.088016 D/Retrofit﹕ X-Xss-Protection: 1; mode=block D/Retrofit﹕ {"trips":[]} D/Retrofit﹕ <--- END HTTP (12-byte body)
Retrofit 2015 • HTTP Clients RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com") .setClient(new AndroidApacheClient()) .build(); RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://api.github.com") .setClient(new MockClient()) .build();
Retrofit 2015 • HTTP Clients RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com") .setClient(new AndroidApacheClient()) .build(); RestAdapter restAdapter = new RestAdapter.Builder() .setEndpoint("https://api.github.com") .setClient(new MockClient()) .build();
Retrofit 2015 • MockClient public class MockClient implements Client {
@Override public Response execute(Request request) throws IOException { Uri uri = Uri.parse(request.getUrl()); List<String> pathSegments = uri.getPathSegments(); String model = pathSegments.get(pathSegments.size() - 1).replace(".json", ""); String path = String.format("test/%s/%s_INDEX.json", model, model); String responseString = convertStreamToString(App.getContext().getAssets().open(path)); return new Response( request.getUrl(), 200, "Success", Collections.<Header>emptyList(), new TypedByteArray( "application/json", responseString.getBytes() ) ); } }
Retrofit 2015 • MockClient public class MockClient implements Client {
@Override public Response execute(Request request) throws IOException { Uri uri = Uri.parse(request.getUrl()); List<String> pathSegments = uri.getPathSegments(); String model = pathSegments.get(pathSegments.size() - 1).replace(".json", ""); String path = String.format("test/%s/%s_INDEX.json", model, model); String responseString = convertStreamToString(App.getContext().getAssets().open(path)); return new Response( request.getUrl(), 200, "Success", Collections.<Header>emptyList(), new TypedByteArray( "application/json", responseString.getBytes() ) ); } }
Retrofit 2015 • Next time: RxJava
Paris, 22 Janvier 2015 Applidium 20 rue Sainte-Croix de la
Bretonnerie 75004 Paris www.applidium.com Merci