Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
はやい・やすい・うまい!スタートアップでも使える Retrofit + RxJava で瞬間A...
Search
Fumihiko Shiroyama
July 14, 2017
Technology
2
600
はやい・やすい・うまい!スタートアップでも使える Retrofit + RxJava で瞬間APIクッキングレシピ
はやい・やすい・うまい!スタートアップでも使える Retrofit + RxJava で瞬間APIクッキングレシピ
Fumihiko Shiroyama
July 14, 2017
Tweet
Share
More Decks by Fumihiko Shiroyama
See All by Fumihiko Shiroyama
The world of Android wireless communications without Internet
srym
1
130
AWS Device FarmとCircleCIでAndroidのUIテストを自動化しよう
srym
1
5k
Spring BootをKotlinで作成しAmazon Elastic Container Service (ECS) で稼働させる
srym
6
1.9k
iOSDC_2019_DeviceFarm.pdf
srym
8
19k
世界で戦うエンジニアになるために_公開用.pdf
srym
18
45k
Unit Testing in a Nutshell - DroidKaigi 2018
srym
11
15k
Clean Architecture & TDD
srym
1
3.8k
I/O 2017 Short Report
srym
0
310
Mock Partially using Dagger
srym
0
650
Other Decks in Technology
See All in Technology
AWSマルチアカウント統制環境のすゝめ / 20250115 Mitsutoshi Matsuo
shift_evolve
0
100
comilioとCloudflare、そして未来へと向けて
oliver_diary
6
430
[IBM TechXchange Dojo]Watson Discoveryとwatsonx.aiでRAGを実現!座学①
siyuanzh09
0
110
Copilotの力を実感!3ヶ月間の生成AI研修の試行錯誤&成功事例をご紹介。果たして得たものとは・・?
ktc_shiori
0
330
深層学習と3Dキャプチャ・3Dモデル生成(土木学会応用力学委員会 応用数理・AIセミナー)
pfn
PRO
0
450
AWSサービスアップデート 2024/12 Part3
nrinetcom
PRO
0
140
CDKのコードレビューを楽にするパッケージcdk-mentorを作ってみた/cdk-mentor
tomoki10
0
200
Cloudflareで実現する AIエージェント ワークフロー基盤
kmd09
0
280
エンジニアリングマネージャー視点での、自律的なスケーリングを実現するFASTという選択肢 / RSGT2025
yoshikiiida
4
3.6k
When Windows Meets Kubernetes…
pichuang
0
300
GoogleのAIエージェント論 Authors: Julia Wiesinger, Patrick Marlow and Vladimir Vuskovic
customercloud
PRO
0
110
re:Invent 2024のふりかえり
beli68
0
100
Featured
See All Featured
Testing 201, or: Great Expectations
jmmastey
41
7.2k
A designer walks into a library…
pauljervisheath
205
24k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
8
1.2k
Building Applications with DynamoDB
mza
93
6.2k
How to train your dragon (web standard)
notwaldorf
89
5.8k
What's in a price? How to price your products and services
michaelherold
244
12k
Typedesign – Prime Four
hannesfritz
40
2.5k
Agile that works and the tools we love
rasmusluckow
328
21k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.4k
Git: the NoSQL Database
bkeepers
PRO
427
64k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
120k
Being A Developer After 40
akosma
89
590k
Transcript
͍ɾ͍͢ɾ͏·͍ʂ ελʔτΞοϓͰ͑Δ Retrofit + RxJava ͰॠؒAPIΫο ΩϯάϨγϐ @fushiroyama
About Me • Fumihiko Shiroyama • Android App Developer •
https://github.com/srym
How to implement REST Client? • HTTP Client • Thread
Executer • JSON Deserializer • Integration with RxJava
Retrofit
Retrofit • A type-safe HTTP client for Android and Java
• http://square.github.io/retrofit/ • by Square
Install // Retrofit compile "com.squareup.retrofit2:retrofit:${retrofitVersion}" compile "com.squareup.retrofit2:adapter-rxjava2:${retrofitVersion}" compile "com.squareup.retrofit2:converter-gson:${retrofitVersion}" //
RxJava compile 'io.reactivex.rxjava2:rxandroid:2.0.1' compile "io.reactivex.rxjava2:rxjava:2.1.1"
Retrofit public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user);
}
Retrofit Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build(); GitHubService service
= retrofit.create(GitHubService.class);
Retrofit GitHubService service = retrofit.create(GitHubService.class); Call<List<Repo>> repos = service.listRepos("srym"); //
synchronous call Response<List<Repo>> response = repos.execute(); // asynchronous call repos.enqueue( /* callback here */ );
Integration with RxJava Retrofit retrofit = new Retrofit.Builder() .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create(gson))
.baseUrl("https://api.github.com/") .build();
Change Return Type public interface GitHubService { @GET("users/{user}/repos") Single<List<Repo>> listRepos(@Path("user")
String user); }
Subscribe Single<List<Repo>> repos = service.listRepos("srym") repos .subscribe( list -> doSomethingToList(list),
throwable -> Timber.d(throwable.getMessage(), throwable), () -> Timber.d("complete") );
Link • RxJava+RetrofitͰAPI௨৴पΓΛ࣮͢Δ͏͑ Ͱ࠷ݶͷࣝΛ30Ͱ٧ΊࠐΉ • http://qiita.com/FumihikoSHIROYAMA/ items/201536d9b45ef21b6bc7
Link • RetrofitΛͬͨOAuth࠶ೝূΞϓϩʔν • http://qiita.com/FumihikoSHIROYAMA/ items/ac1beaeaa9b4baaed939
Link • RetrofitΛͬͨAPIݺͼग़͠ͰϦΧόϦՄೳ ͳHTTPΤϥʔΛͲ͏ѻ͏͔ • http://qiita.com/FumihikoSHIROYAMA/ items/65d52aea1a9f324d347e
What's Good about Retrofit + Rx • Easy to define
• Easy to compose • Easy to test
Test • MockWebServer • TestSubscriber
MockWebServer • A scriptable web server for testing HTTP clients
• https://github.com/square/okhttp/tree/ master/mockwebserver
MockWebServer private final MockWebServer mockWebServer = new MockWebServer();
MockWebServer Dispatcher dispatcher = new Dispatcher() { @Override public MockResponse
dispatch(RecordedRequest request) throws InterruptedException { return new MockResponse().setResponseCode(404); } }; mockWebServer.setDispatcher(dispatcher); mockWebServer.start();
MockWebServer @Override public MockResponse dispatch(RecordedRequest request) { if (request ==
null || request.getPath() == null) { return new MockResponse().setResponseCode(400); } if (request.getPath().matches("/users/.+/repos")) { return new MockResponse().setBody( readJsonFromResources("users_repos.json") ).setResponseCode(200); } return new MockResponse().setResponseCode(404); }
MockWebServer Retrofit retrofit = new Retrofit.Builder() .baseUrl(mockWebServer.url("")) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build();
GitHubService gitHubService = retrofit.create(GitHubService.class);
TestSubscriber • A TestSubscriber is a variety of Subscriber that
you can use for unit testing, to perform assertions, inspect received events, or wrap a mocked Subscriber. • http://reactivex.io/RxJava/javadoc/rx/ observers/TestSubscriber.html
TestSubscriber restGitHubDataSource .listRepos("srym") .test();
TestSubscriber List<Repo> repos = restGitHubDataSource.listRepos("srym") .test() .await() .assertNoErrors() .assertComplete() .values()
.get(0); assertThat(repos).isNotNull();
TestSubscriber • https://github.com/srym/Architecture • https://github.com/srym/Architecture/blob/ master/app/src/test/java/us/shiroyama/ android/architecture/infrastructure/ repository/datasource/remote/ RestGitHubDataSourceTest.java
Easy to compose • Rx's Observable is easily & flexibly
combined • Avoid callback hells
Easy to compose public class GitHubInfraRepository implements GitHubRepository { private
final RemoteGitHubDataSource remoteDataSource; private final RepoMapper mapper; @Inject public GitHubInfraRepository(RemoteGitHubDataSource remoteDataSource, RepoMapper mapper) { this.remoteDataSource = remoteDataSource; this.mapper = mapper; } @Override public Single<List<RepoModel>> listRepos(@NonNull String user) { return remoteDataSource .listRepos(user) .map(mapper::convert); } }
Easy to compose private final RemoteGitHubDataSource remoteDataSource; private final LocalGitHubDataSource
localGitHubDataSource; private final RepoMapper mapper; @Inject public GitHubInfraRepository(RemoteGitHubDataSource remoteDataSource, LocalGitHubDataSource localGitHubDataSource, RepoMapper mapper) { this.remoteDataSource = remoteDataSource; this.localGitHubDataSource = localGitHubDataSource; this.mapper = mapper; }
Easy to compose @Override public Single<List<RepoModel>> listRepos(@NonNull String user) {
return remoteDataSource .listRepos(user) .map(mapper::convert);
Easy to compose public Single<List<RepoModel>> listRepos(@NonNull String user) { return
localGitHubDataSource .listRepos(user) .onErrorResumeNext( remoteDataSource .listRepos(user) .retry(DEFAULT_RETRY) .doOnSuccess(localGitHubDataSource::save) ) .map(mapper::convert);
Android Clean Architecture • android10/Android-CleanArchitecture • https://github.com/android10/Android- CleanArchitecture • srym/Architecture
• https://github.com/srym/Architecture
None