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
あなたの知らないクラフトビールの世界
miura55
0
130
ABWGのRe:Cap!
hm5ug
1
120
生成AI × 旅行 LLMを活用した旅行プラン生成・チャットボット
kominet_ava
0
160
Oracle Base Database Service 技術詳細
oracle4engineer
PRO
6
54k
WantedlyでのKotlin Multiplatformの導入と課題 / Kotlin Multiplatform Implementation and Challenges at Wantedly
kubode
0
250
なぜfreeeはハブ・アンド・スポーク型の データメッシュアーキテクチャにチャレンジするのか?
shinichiro_joya
2
490
生成AIのビジネス活用
seosoft
0
110
AWS re:Invent 2024 recap in 20min / JAWSUG 千葉 2025.1.14
shimy
1
100
.NET 最新アップデート ~ AI とクラウド時代のアプリモダナイゼーション
chack411
0
200
2025年のARグラスの潮流
kotauchisunsun
0
790
メールヘッダーを見てみよう
hinono
0
110
技術に触れたり、顔を出そう
maruto
1
150
Featured
See All Featured
The Language of Interfaces
destraynor
155
24k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.5k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
98
18k
Music & Morning Musume
bryan
46
6.3k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.1k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
232
17k
GraphQLの誤解/rethinking-graphql
sonatard
68
10k
How to Create Impact in a Changing Tech Landscape [PerfNow 2023]
tammyeverts
49
2.2k
Raft: Consensus for Rubyists
vanstee
137
6.7k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
251
21k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Building a Scalable Design System with Sketch
lauravandoore
460
33k
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