Retrofit

About me




  • Deuphil Kaufmann
  • Android Engineer @ IntroMe
  • Ilonggo
  • Java/Android/Mobile
  • twitter.com/deubaka


What about Retrofit?




  • Made by Square (Woot!)
  • ReST client, not an HTTP client
  • Built for Android and Java
  • Type-safe and response agnostic

    Setting up Retrofit



    Gradle

     compile 'com.squareup.retrofit:retrofit:1.9.0'


    OkHttp (Optional)

     compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.0' 
     compile 'com.squareup.okhttp:okhttp:2.0.0'
    

    Requesting | GET Query


    HttpUrlConnection-way

    HttpURLConnection getTodoConnection = null;
    try {
    getTodoConnection = (HttpURLConnection) mGetQueryUrl.openConnection();
    } catch (IOException e) {
    Log.e(TAG, "Error: " + e.getMessage());
    }

    try {
    String response = parseResponse(getTodoConnection.getInputStream());
    } catch (IOException e) {
    Log.e(TAG, "Error: " + e.getMessage());
    } finally {
    getTodoConnection.disconnect();
    }

    // Send response somewhere (eg. Event bus or LocalBroadcastReceiver)

    ...then off load it to a AsyncTask or IntentService and a few boilerplate codes...

    Requesting | GET Query


    Retrofit-way

    public interface TodoApi {
    
        @GET("/todos")
    void getTodosByUserId(@Query("userId") Long userId, Callback<Todo[]> todos);

    }

    ... then create a RestAdapter once and create,

    RestAdapter restAdapter = new RestAdapter.Builder().setEndpoint(Api.BASE_URL).build();
    mTodoApi = restAdapter.create(TodoApi.class);

    mTodoApi.getTodosByUserId(1L, new Callback<Todo[]>() {
    @Override
    public void success(Todo[] todos, Response response) {
    // Do something on success
    }

    @Override
    public void failure(RetrofitError error) {
    // Do something on failure
    }
    })
    ;

    Requesting | POST

    Retrofit-way
    public interface TodoApi {
    @FormUrlEncoded
    @POST("/todos")
    void addTodo(@Field("userId") Long userId, @Field("id") Long id,
    @Field("title") String title, @Field("completed") boolean completed,
    Callback<Todo> todo);

    @POST("/todos")
    void addTodo(@Body Todo newTodo, Callback<Todo> todo);
    }
    ...then...
    mTodoApi.addTodo(newTodo, new Callback<Todo>() {
    @Override
    public void success(Todo todo, Response response) {
    // Do something on success
    }

    @Override
    public void failure(RetrofitError error) {
    // Do something on failure
    }
    })
    ;

    Requesting



    • @PUT
    • @DELETE
    • @PATCH
    • @FieldMap
    • @QueryMap
    • @Multipart
    • @Part (for mutlipart requests via Typed* classes)
    • @Header
    • RxJava Supports
    • ...check out the docs!

      Requesting | Request Interceptors

      public class ThrottlingInterceptor implements RequestInterceptor {
      private static final String TAG = ThrottlingInterceptor.class.getSimpleName();

      private long lastRequest = 0L;
      private final long maxRequestSpeed;
      private final Lock requestLock = new ReentrantLock();

      public ThrottlingInterceptor(long maxRequestSpeed) {
      this.maxRequestSpeed = maxRequestSpeed;
      }

      @Override
      public void intercept(RequestFacade request) {
      requestLock.lock();

      try {
      long curTime = System.currentTimeMillis();
      long diff = curTime - lastRequest;

      if (diff < maxRequestSpeed)
      try {
      Thread.sleep(maxRequestSpeed - diff);
      } catch (InterruptedException e) {
      Log.e(TAG, "Error: " + e.getMessage());
      }

      lastRequest = System.currentTimeMillis();
      } finally { requestLock.unlock(); }
      }
      }

      Requesting | Request Interceptors

      Continued...
      RestAdapter restAdapter = new RestAdapter.Builder()
      // Throttle every 1s
      .setRequestInterceptor(new ThrottlingInterceptor(1000))
      .setEndpoint(Api.BASE_URL).build();
      mTodoApi = restAdapter.create(TodoApi.class);

      Requesting | Error Handler

      public class TodoErrorHandler implements ErrorHandler {
      // Variable declarations and constructor...

      @Override
      public Throwable handleError(RetrofitError cause) {
      if (cause.getKind() == RetrofitError.Kind.NETWORK) {
      mToastHandler.post(new Runnable() {
      @Override
      public void run() {
      Toast.
      makeText(mContext, R.string.error_network, Toast.LENGTH_SHORT).show();
      }
      })
      ;
      } else if (cause.getKind() == RetrofitError.Kind.HTTP) {
      mToastHandler.post(new Runnable() {
      @Override
      public void run() {
      Toast.
      makeText(mContext, R.string.error_http, Toast.LENGTH_SHORT).show();
      }
      })
      ;
      }
      return cause.getCause();
      }
      }

      Benchmark




      (http://instructure.github.io/blog/2013/12/09/volley-vs-retrofit/)

      Retrofit 2.0




      • Synchronous/Asynchronous call agnostic
      • Cancellable requests
      • Better Request/Response Interceptors
      • Auto-retry of requests
      • Extensions support
      • ...and more!






      END

      Questions? Clarifications?




      PADC - Retrofit

      By Deuphil Kaufmann (deu)

      PADC - Retrofit

      A presentation on Retrofit used for PADC's 2nd Meetup of 2015 @ KLabs.

      • 1,479