SlideShare uma empresa Scribd logo
1 de 18
Retrofit2 & OkHttp
でAndroidのHTTP通信が快適だにゃん
1
日本Androidの会埼玉支部 @sakura_bird1
2016/01/23
さくら@sakura_bird1
ABOUT ME
• 多分ハタチ
• 野良プログラマー3年目ぐらい
• Android受託開発で糊口をしのぐ
• 最近Player!というアプリを作ってます。
もうすぐAndroid版リリース(?)
• 一生プログラマー
• 今年はSwiftやりたい
OkHttp
• Square社のHTTPクライアント(http://square.github.io/okhttp/)
• http通信が簡単に書ける
• 通信状況が悪い時は再接続してくれる
• HTTP/2 ,SPDYをサポート
• Okio(java.io)に依存
• 強力なInterceptor (request前処理,ロギング,ヘッダー,gzip圧縮 )
• コネクションプーリング、キャッシング、同期/非同期call、リダイレクト他
3
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と相性がいいらしいがここでは割愛
4
使用例
public interface GitHubService {
@FormUrlEncoded
@POST("user/edit")
Call<User> updateUser(@Field("first_name") String first,
@Field("last_name") String last);
}
Interfaceでエンドポイント、メソッド、パラメータを定義
Request body変換用エンティティクラスを指定
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を指定
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する
便利な使い方
@Headers({
"Accept: application/vnd.github.v3.full+json",
"User-Agent: Retrofit-Sample-App"
})
@GET("users/{username}")
Call<User> getUser(@Path("username") String username);
HEADER
1. Interfaceに記述する方法
Headerやendpointに変数を指定できる
HEADER
2. 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);
}
});
LOGGING
LoggingInterceptorを使う
if (BuildConfig.DEBUG) {
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.networkInterceptors().add(interceptor);
}
共通処理をまとめたい
その1.エラー処理
retrofit.Callbackインターフェイスを実装し独自クラスを使う
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>
このあたりに毎回同じエラー処理を書きたい
例えばこんな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());
}
}
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の代わりに指定する
共通処理をまとめたい
その2.Retrofitにセットする値はいつも同じ
汎用メソッドを用意しておく
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);

Mais conteúdo relacionado

Mais procurados

Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話KEISUKE KONISHI
 
DockerコンテナでGitを使う
DockerコンテナでGitを使うDockerコンテナでGitを使う
DockerコンテナでGitを使うKazuhiro Suga
 
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021Hiroshi Tokumaru
 
こわくない Git
こわくない Gitこわくない Git
こわくない GitKota Saito
 
Dockerfile を書くためのベストプラクティス解説編
Dockerfile を書くためのベストプラクティス解説編Dockerfile を書くためのベストプラクティス解説編
Dockerfile を書くためのベストプラクティス解説編Masahito Zembutsu
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説murachue
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法Tetsutaro Watanabe
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugMasatoshi Tada
 
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -onozaty
 
Zabbixのパフォーマンスチューニング & インストール時の注意点
Zabbixのパフォーマンスチューニング & インストール時の注意点Zabbixのパフォーマンスチューニング & インストール時の注意点
Zabbixのパフォーマンスチューニング & インストール時の注意点Kodai Terashima
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところY Watanabe
 
トランクベース開発を活用して爆速に開発した話
トランクベース開発を活用して爆速に開発した話トランクベース開発を活用して爆速に開発した話
トランクベース開発を活用して爆速に開発した話Tier_IV
 
Linuxのsemaphoreとmutexを見る 
Linuxのsemaphoreとmutexを見る Linuxのsemaphoreとmutexを見る 
Linuxのsemaphoreとmutexを見る wata2ki
 
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話Koichiro Matsuoka
 
Dockerfileを改善するためのBest Practice 2019年版
Dockerfileを改善するためのBest Practice 2019年版Dockerfileを改善するためのBest Practice 2019年版
Dockerfileを改善するためのBest Practice 2019年版Masahito Zembutsu
 
Hyper-V を Windows PowerShell から管理する
Hyper-V を Windows PowerShell から管理するHyper-V を Windows PowerShell から管理する
Hyper-V を Windows PowerShell から管理するjunichi anno
 
シリコンバレーの「何が」凄いのか
シリコンバレーの「何が」凄いのかシリコンバレーの「何が」凄いのか
シリコンバレーの「何が」凄いのかAtsushi Nakada
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)Takuto Wada
 
Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門Etsuji Nakai
 

Mais procurados (20)

Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話Swaggerでのapi開発よもやま話
Swaggerでのapi開発よもやま話
 
DockerコンテナでGitを使う
DockerコンテナでGitを使うDockerコンテナでGitを使う
DockerコンテナでGitを使う
 
SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021SPAセキュリティ入門~PHP Conference Japan 2021
SPAセキュリティ入門~PHP Conference Japan 2021
 
こわくない Git
こわくない Gitこわくない Git
こわくない Git
 
Dockerfile を書くためのベストプラクティス解説編
Dockerfile を書くためのベストプラクティス解説編Dockerfile を書くためのベストプラクティス解説編
Dockerfile を書くためのベストプラクティス解説編
 
目grep入門 +解説
目grep入門 +解説目grep入門 +解説
目grep入門 +解説
 
MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法MongoDBが遅いときの切り分け方法
MongoDBが遅いときの切り分け方法
 
Java ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsugJava ORマッパー選定のポイント #jsug
Java ORマッパー選定のポイント #jsug
 
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
今からでも遅くないDBマイグレーション - Flyway と SchemaSpy の紹介 -
 
Zabbixのパフォーマンスチューニング & インストール時の注意点
Zabbixのパフォーマンスチューニング & インストール時の注意点Zabbixのパフォーマンスチューニング & インストール時の注意点
Zabbixのパフォーマンスチューニング & インストール時の注意点
 
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
ツール比較しながら語る O/RマッパーとDBマイグレーションの実際のところ
 
トランクベース開発を活用して爆速に開発した話
トランクベース開発を活用して爆速に開発した話トランクベース開発を活用して爆速に開発した話
トランクベース開発を活用して爆速に開発した話
 
Linuxのsemaphoreとmutexを見る 
Linuxのsemaphoreとmutexを見る Linuxのsemaphoreとmutexを見る 
Linuxのsemaphoreとmutexを見る 
 
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話DDD x CQRS   更新系と参照系で異なるORMを併用して上手くいった話
DDD x CQRS 更新系と参照系で異なるORMを併用して上手くいった話
 
Dockerfileを改善するためのBest Practice 2019年版
Dockerfileを改善するためのBest Practice 2019年版Dockerfileを改善するためのBest Practice 2019年版
Dockerfileを改善するためのBest Practice 2019年版
 
Hyper-V を Windows PowerShell から管理する
Hyper-V を Windows PowerShell から管理するHyper-V を Windows PowerShell から管理する
Hyper-V を Windows PowerShell から管理する
 
Keycloak入門
Keycloak入門Keycloak入門
Keycloak入門
 
シリコンバレーの「何が」凄いのか
シリコンバレーの「何が」凄いのかシリコンバレーの「何が」凄いのか
シリコンバレーの「何が」凄いのか
 
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
SQLアンチパターン - 開発者を待ち受ける25の落とし穴 (拡大版)
 
Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門Linux女子部 systemd徹底入門
Linux女子部 systemd徹底入門
 

Destaque

App indexingでアプリの成長を加速させよう!
App indexingでアプリの成長を加速させよう!App indexingでアプリの成長を加速させよう!
App indexingでアプリの成長を加速させよう!Yukari Sakurai
 
HTTP/2の現状とこれから
HTTP/2の現状とこれからHTTP/2の現状とこれから
HTTP/2の現状とこれからshigeki_ohtsu
 
負荷対策しておもったことまとめ~JMeterでSocket.IOもいけるでよ~
負荷対策しておもったことまとめ~JMeterでSocket.IOもいけるでよ~負荷対策しておもったことまとめ~JMeterでSocket.IOもいけるでよ~
負荷対策しておもったことまとめ~JMeterでSocket.IOもいけるでよ~johgus johgus
 
絶対落ちないアプリの作り方
絶対落ちないアプリの作り方絶対落ちないアプリの作り方
絶対落ちないアプリの作り方Fumihiko Shiroyama
 
Webアプリケーション負荷試験実践入門
Webアプリケーション負荷試験実践入門Webアプリケーション負荷試験実践入門
Webアプリケーション負荷試験実践入門樽八 仲川
 
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践Yoshifumi Kawai
 

Destaque (6)

App indexingでアプリの成長を加速させよう!
App indexingでアプリの成長を加速させよう!App indexingでアプリの成長を加速させよう!
App indexingでアプリの成長を加速させよう!
 
HTTP/2の現状とこれから
HTTP/2の現状とこれからHTTP/2の現状とこれから
HTTP/2の現状とこれから
 
負荷対策しておもったことまとめ~JMeterでSocket.IOもいけるでよ~
負荷対策しておもったことまとめ~JMeterでSocket.IOもいけるでよ~負荷対策しておもったことまとめ~JMeterでSocket.IOもいけるでよ~
負荷対策しておもったことまとめ~JMeterでSocket.IOもいけるでよ~
 
絶対落ちないアプリの作り方
絶対落ちないアプリの作り方絶対落ちないアプリの作り方
絶対落ちないアプリの作り方
 
Webアプリケーション負荷試験実践入門
Webアプリケーション負荷試験実践入門Webアプリケーション負荷試験実践入門
Webアプリケーション負荷試験実践入門
 
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
「黒騎士と白の魔王」gRPCによるHTTP/2 - API, Streamingの実践
 

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

Implements OpenTelemetry Collector in DotNet
Implements OpenTelemetry Collector in DotNetImplements OpenTelemetry Collector in DotNet
Implements OpenTelemetry Collector in DotNetYoshifumi Kawai
 
勉強会force#4 Chatter Integration
勉強会force#4 Chatter Integration勉強会force#4 Chatter Integration
勉強会force#4 Chatter IntegrationKazuki Nakajima
 
Goji とレイヤ化アーキテクチャ
Goji とレイヤ化アーキテクチャGoji とレイヤ化アーキテクチャ
Goji とレイヤ化アーキテクチャShiroyagi Corporation
 
Web socket and gRPC
Web socket and gRPCWeb socket and gRPC
Web socket and gRPCTIS Inc
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputingNoboru Irieda
 
gumiStudy#5 JavaScript でネイティブiPhone/Androidアプリを作る
gumiStudy#5 JavaScript でネイティブiPhone/Androidアプリを作るgumiStudy#5 JavaScript でネイティブiPhone/Androidアプリを作る
gumiStudy#5 JavaScript でネイティブiPhone/Androidアプリを作るgumilab
 
Swift - Result&lt;t>型で結果を返すのは邪道か,王道か
Swift - Result&lt;t>型で結果を返すのは邪道か,王道かSwift - Result&lt;t>型で結果を返すのは邪道か,王道か
Swift - Result&lt;t>型で結果を返すのは邪道か,王道かYuichi Yoshida
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platformToru Yamaguchi
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#信之 岩永
 
Reactive Extensionsで非同期処理を簡単に
Reactive Extensionsで非同期処理を簡単にReactive Extensionsで非同期処理を簡単に
Reactive Extensionsで非同期処理を簡単にYoshifumi Kawai
 
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 SpringGoでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 SpringYahoo!デベロッパーネットワーク
 
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere  - Rxの原則とUniRxにみるデータソースの見つけ方Observable Everywhere  - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方Yoshifumi Kawai
 
Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)ryos36
 
20130315 abc firefox_os
20130315 abc firefox_os20130315 abc firefox_os
20130315 abc firefox_osTomoaki Konno
 

Semelhante a Retrofit2 &OkHttp 
でAndroidのHTTP通信が快適だにゃん (20)

Implements OpenTelemetry Collector in DotNet
Implements OpenTelemetry Collector in DotNetImplements OpenTelemetry Collector in DotNet
Implements OpenTelemetry Collector in DotNet
 
勉強会force#4 Chatter Integration
勉強会force#4 Chatter Integration勉強会force#4 Chatter Integration
勉強会force#4 Chatter Integration
 
RとWeb API
RとWeb APIRとWeb API
RとWeb API
 
Goji とレイヤ化アーキテクチャ
Goji とレイヤ化アーキテクチャGoji とレイヤ化アーキテクチャ
Goji とレイヤ化アーキテクチャ
 
Web socket and gRPC
Web socket and gRPCWeb socket and gRPC
Web socket and gRPC
 
Python physicalcomputing
Python physicalcomputingPython physicalcomputing
Python physicalcomputing
 
gumiStudy#5 JavaScript でネイティブiPhone/Androidアプリを作る
gumiStudy#5 JavaScript でネイティブiPhone/Androidアプリを作るgumiStudy#5 JavaScript でネイティブiPhone/Androidアプリを作る
gumiStudy#5 JavaScript でネイティブiPhone/Androidアプリを作る
 
Swift - Result&lt;t>型で結果を返すのは邪道か,王道か
Swift - Result&lt;t>型で結果を返すのは邪道か,王道かSwift - Result&lt;t>型で結果を返すのは邪道か,王道か
Swift - Result&lt;t>型で結果を返すのは邪道か,王道か
 
Inside mobage platform
Inside mobage platformInside mobage platform
Inside mobage platform
 
HTML5&API総まくり
HTML5&API総まくりHTML5&API総まくり
HTML5&API総まくり
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#
 
Ajax 応用
Ajax 応用Ajax 応用
Ajax 応用
 
Reactive Extensionsで非同期処理を簡単に
Reactive Extensionsで非同期処理を簡単にReactive Extensionsで非同期処理を簡単に
Reactive Extensionsで非同期処理を簡単に
 
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 SpringGoでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
 
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere  - Rxの原則とUniRxにみるデータソースの見つけ方Observable Everywhere  - Rxの原則とUniRxにみるデータソースの見つけ方
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
Data APIの基本
Data APIの基本Data APIの基本
Data APIの基本
 
Connect with Data API
Connect with Data APIConnect with Data API
Connect with Data API
 
Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)Polyphony の行く末(2018/3/3)
Polyphony の行く末(2018/3/3)
 
20130315 abc firefox_os
20130315 abc firefox_os20130315 abc firefox_os
20130315 abc firefox_os
 

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

  • 2. さくら@sakura_bird1 ABOUT ME • 多分ハタチ • 野良プログラマー3年目ぐらい • Android受託開発で糊口をしのぐ • 最近Player!というアプリを作ってます。 もうすぐAndroid版リリース(?) • 一生プログラマー • 今年はSwiftやりたい
  • 3. OkHttp • Square社のHTTPクライアント(http://square.github.io/okhttp/) • http通信が簡単に書ける • 通信状況が悪い時は再接続してくれる • HTTP/2 ,SPDYをサポート • Okio(java.io)に依存 • 強力なInterceptor (request前処理,ロギング,ヘッダー,gzip圧縮 ) • コネクションプーリング、キャッシング、同期/非同期call、リダイレクト他 3
  • 4. 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と相性がいいらしいがここでは割愛 4
  • 6. public interface GitHubService { @FormUrlEncoded @POST("user/edit") Call<User> updateUser(@Field("first_name") String first, @Field("last_name") String last); } Interfaceでエンドポイント、メソッド、パラメータを定義 Request body変換用エンティティクラスを指定
  • 7. 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を指定
  • 8. 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する
  • 10. @Headers({ "Accept: application/vnd.github.v3.full+json", "User-Agent: Retrofit-Sample-App" }) @GET("users/{username}") Call<User> getUser(@Path("username") String username); HEADER 1. Interfaceに記述する方法 Headerやendpointに変数を指定できる
  • 11. HEADER 2. 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); } });
  • 12. LOGGING LoggingInterceptorを使う if (BuildConfig.DEBUG) { HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); httpClient.networkInterceptors().add(interceptor); }
  • 14. 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> このあたりに毎回同じエラー処理を書きたい
  • 15. 例えばこんな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()); } }
  • 16. 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の代わりに指定する
  • 18. 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);