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
140
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
66
ML Session n°7
acq
0
29
ML Session n°6
acq
0
47
ML Session n°5
acq
0
66
ML Session n°4
acq
0
44
ML Session n°3
acq
0
110
ML Session n°2
acq
1
100
ML Session n°1
acq
0
100
Other Decks in Technology
See All in Technology
AI コーディングと人間の認知スループット / CTO Night & Day 2026 Morning Session / AI Coding and Human Cognitive Throughput
prog893
4
1.1k
CTO Night|NotionのAIエージェントとFDE
kzkhykw1991
0
110
フロントエンドカンファレンス関西2026 - 速すぎるUIに、待ち時間を
teamlab
PRO
0
130
Kiro Crewをはじめよう
kizawa2020
1
160
ストレスなくAIと付き合いたい!こんなときどうしてる?
namiki64
3
520
Optunaの最新リリースv5.0について
pfn
PRO
0
120
20261017福岡devIO 「AIは"良いダッシュボード"を作れるか?
jtakeda
0
150
DWH の限界突破! AI エージェント向け爆速リアルタイムデータ基盤 ClickHouse
jozono
1
470
DGX Spark でどこまでハッキングができるのか?
kash1064
3
1.3k
会社説明資料
persolserverworks
0
9.8k
USB PDを使ってスマホを労わりたい
raspython3
0
180
AIにシークレットを見せない、WSL2で安全な開発環境
yazm
0
300
Featured
See All Featured
So, you think you're a good person
axbom
PRO
2
2.2k
Keith and Marios Guide to Fast Websites
keithpitt
413
23k
Build The Right Thing And Hit Your Dates
maggiecrowley
39
3.5k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
PRO
203
77k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
16
2.2k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
22k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
990
Ethics towards AI in product and experience design
skipperchong
2
430
The Mindset for Success: Future Career Progression
greggifford
PRO
0
540
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
340
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
710
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
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