Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Retrofit

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

 Retrofit

Avatar for Adrien Couque

Adrien Couque

January 22, 2015
Tweet

More Decks by Adrien Couque

Other Decks in Technology

Transcript

  1. 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) {
 // …
 }
 });
  2. 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
 }
 });
  3. 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
 }
 });
  4. 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
 }
 });
  5. 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
 }
 });
  6. 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;
 }
 }
  7. 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;
 }
 }
  8. 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;
 }
 }
  9. 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;
 }
 }
  10. 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;
 }
 }
  11. Retrofit 2015 • Synchronous vs Asynchronous @GET("/associate/annual-salaries.json")
 List<AnnualSalary> getAnnualSalaries();
 


    @GET("/associate/annual-salaries.json")
 void getAnnualSalaries(Callback<List<AnnualSalary>> callback);
  12. Retrofit 2015 • Query @GET("/users")
 List<User> groupList(@Query("sort") String sort);
 


    @GET("/users")
 List<User> groupList(@QueryMap Map<String, String> options);
  13. 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);
  14. 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);
  15. 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);
  16. 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);
  17. 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); 
 }
  18. 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" }
  19. 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);
 }
  20. 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'
  21. 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);
  22. 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);
  23. 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);
  24. 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);
  25. 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);
  26. Retrofit 2015 • Jackson: property names @JsonProperty("id")
 protected String uuid;

    @JsonIgnore
 protected String uuid; @JsonProperty
 public String getId() {
 return uuid;
 }
  27. Retrofit 2015 • Jackson: property names @JsonProperty("id")
 protected String uuid;

    @JsonIgnore
 protected String uuid; @JsonProperty
 public String getId() {
 return uuid;
 }
  28. 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;
 }
  29. 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;
 }
  30. 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;

  31. 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;
 }
  32. 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;

  33. 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;
 }
  34. 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)
  35. 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();
  36. 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();
  37. 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()
 )
 );
 }
 }
  38. 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()
 )
 );
 }
 }
  39. Paris, 22 Janvier 2015 Applidium 20 rue Sainte-Croix de la

    Bretonnerie 75004 Paris www.applidium.com Merci