retrofit2 &okhttp でandroidのhttp通信が快適だにゃん

18
Retrofit2 & OkHttp で Android で HTTP ででででででででで でで Android でででででで @sakura_bird1 2016/01/23

Upload: yukari-sakurai

Post on 12-Jan-2017

3.448 views

Category:

Engineering


7 download

TRANSCRIPT

Page 1: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

Retrofit2 & OkHttpで Android の HTTP 通信が快適だにゃん

日本 Android の会埼玉支部 @sakura_bird12016/01/23

Page 2: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

さくら @sakura_bird1ABOUT ME

• 多分ハタチ• 野良プログラマー 3 年目ぐらい• Android 受託開発で糊口をしのぐ• 最近 Player! というアプリを作ってます。もうすぐ Android 版リリース (?)

• 一生プログラマー• 今年は Swift やりたい

Page 3: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

OkHttp• Square 社の HTTP クライアント (http://square.github.io/okhttp/)

• http 通信が簡単に書ける• 通信状況が悪い時は再接続してくれる• HTTP/2 ,SPDY をサポート• Okio(java.io) に依存• 強力な Interceptor (request 前処理 , ロギング , ヘッダー ,gzip 圧縮 )

• コネクションプーリング、キャッシング、同期/非同期 call 、リダイレクト他

Page 4: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

Retrofit• Square 社の HTTP クライアント用ライブラリ (http://square.github.io/

retrofit/)

• REST API を Java Interface 、アノテーションの形でシンプルに書ける• 最新のバージョンは Retrofit version2.0.0-beta3

• Retrofit2 系と 1 系はかなり大きく違っている• Http body の変換用にいくつかの selialization 用ライブラリに使えるコンバーターが用意されている (Gson, Jackson, Moshi, Protobuf, Wire, Simple XML)

• RxAndroid と相性がいいらしいがここでは割愛

Page 5: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

使用例

Page 6: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

public interface GitHubService {

@FormUrlEncoded @POST("user/edit") Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last);}

Interface でエンドポイント、メソッド、パラメータを定義

Request body 変換用エンティティクラスを指定

Page 7: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

Retrofit retrofit = new Retrofit.Builder() .baseUrl(“https://api.github.com")  .client(httpClient) .addConverterFactory(GsonConverterFactory.create()) .build();

GitHubService service = retrofit.create(GitHubService.class);

OkHttpClient httpClient = new OkHttpClient(); ↑ これがなくても OK 。自動的に OkHttp を使用する。

通信処理  Retrofit  セットアップ

Retrofit のオブジェクトを生成する Request body 変換用 converter を指定

Page 8: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

Call<User> task = service.updateUser(firstName, lastName); task.enqueue(new Callback<User>() { @Override public void onResponse(Response<User> response, Retrofit retrofit) { if (response != null && response.body() != null) { // response.body() に User クラスに変換されたオブジェクト // が入っている } } @Override public void onFailure(Throwable t) { } });

API を call する

Page 9: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

便利な使い方

Page 10: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

@Headers({ "Accept: application/vnd.github.v3.full+json", "User-Agent: Retrofit-Sample-App"})@GET("users/{username}")Call<User> getUser(@Path("username") String username);

HEADER1. Interface に記述する方法

Header や endpoint に変数を指定できる

Page 11: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

HEADER2. OkHttp の interceptor を使って記述する方法どの request でも必ず指定するヘッダーはこっちを使った方が便利

httpClient.interceptors().add(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Request original = chain.request();

Request request = original.newBuilder() .header(“Hoge-Version”,”1.0”) .header(“Client-OS”,”Android”) .method(original.method(), original.body()) .build();

return chain.proceed(request); } });

Page 12: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

LOGGINGLoggingInterceptor を使う

if (BuildConfig.DEBUG) { HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); httpClient.networkInterceptors().add(interceptor); }

Page 13: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

共通処理をまとめたいその1.エラー処理

retrofit.Callback インターフェイスを実装し独自クラスを使う

Page 14: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

Call<User> task = service.updateUser(firstName, lastName); task.enqueue(new Callback<User>() { @Override public void onResponse(Response<User> response, Retrofit retrofit) { } } @Override public void onFailure(Throwable t) { } });

デフォルトの Callback<T>

このあたりに毎回同じエラー処理を書きたい

Page 15: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

例えばこんな Callback クラスを用意しますpublic class NetworkCallback<T> implements Callback<T> { private Context mContext;

public NetworkCallback(Context context) { mContext = context; } @Override public void onResponse(Response<T> response, Retrofit retrofit) { if (response != null && response.errorBody() != null) { try { if (response.code() > 400) { String errorBody = response.errorBody().string(); Logger.e("error :" + errorBody + " code:" + response.code()); ClientHelper.ApiError apiError = ClientHelper.onApiError(response.code(), errorBody); showDialog(mContext, mContext.getString(R.string.errorOccured), apiError.getMessage()); return; } } catch (IOException e) { e.printStackTrace(); showDialog(mContext, mContext.getString(R.string.errorOccured), ClientHelper.ApiError.UNKNOWN.getMessage()); return; } } if (response == null || response.body() == null) { Logger.e("response or response body=null"); showDialog(mContext, mContext.getString(R.string.errorOccured), ClientHelper.ApiError.UNKNOWN.getMessage()); } }

@Override public void onFailure(Throwable t) { if (t != null) { t.fillInStackTrace(); Logger.e("Throwable t:" + t.getCause() + " " + t.getMessage()); } else { Logger.e("Cound not access server"); } showDialog(mContext, mContext.getString(R.string.errorOccured), ClientHelper.ApiError.OFFLINE.getMessage()); }}

Page 16: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

UserClient client = ClientHelper.createService(UserClient.class); Call<User> task = client.show(); task.enqueue(new NetworkCallback<User>(mContext) { @Override public void onResponse(Response<User> response, Retrofit retrofit) { super.onResponse(response, retrofit); if (response != null && response.errorBody() != null) { return; } if (response != null && response.body() != null) { // somethings } } @Override public void onFailure(Throwable t) { super.onFailure(t); } });

デフォルトの Callback の代わりに指定する

Page 17: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

共通処理をまとめたいその2. Retrofit にセットする値はいつも同じ

汎用メソッドを用意しておく

Page 18: Retrofit2 &OkHttp でAndroidのHTTP通信が快適だにゃん

private static Retrofit.builder builder; public static <S> S createService(Class<S> serviceClass) { builder.baseUrl(PlayerApplication.getContext().getString(R.string.API_BASE_URL)); Retrofit retrofit = builder .client(httpClient) .addConverterFactory(GsonConverterFactory.create()) .build(); return retrofit.create(serviceClass); }

汎用メソッド

汎用メソッドを使ってオブジェクトを生成UsersClient client = ClientHelper.createService(UsersClient.class);