Upgrade to Pro — share decks privately, control downloads, hide ads and more …

はやい・やすい・うまい!スタートアップでも使える Retrofit + RxJava で瞬間APIクッキングレシピ

はやい・やすい・うまい!スタートアップでも使える Retrofit + RxJava で瞬間APIクッキングレシピ

はやい・やすい・うまい!スタートアップでも使える Retrofit + RxJava で瞬間APIクッキングレシピ

3cca191bf3064fd059ea2c3d6022afbd?s=128

Fumihiko Shiroyama

July 14, 2017
Tweet

Transcript

  1. ͸΍͍ɾ΍͍͢ɾ͏·͍ʂ
 ελʔτΞοϓͰ΋࢖͑Δ Retrofit + RxJava ͰॠؒAPIΫο ΩϯάϨγϐ @fushiroyama

  2. About Me • Fumihiko Shiroyama • Android App Developer •

    https://github.com/srym
  3. How to implement REST Client? • HTTP Client • Thread

    Executer • JSON Deserializer • Integration with RxJava
  4. Retrofit

  5. Retrofit • A type-safe HTTP client for Android and Java

    • http://square.github.io/retrofit/ • by Square
  6. 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"
  7. Retrofit public interface GitHubService { @GET("users/{user}/repos") Call<List<Repo>> listRepos(@Path("user") String user);

    }
  8. Retrofit Retrofit retrofit = new Retrofit.Builder() .baseUrl("https://api.github.com/") .build(); GitHubService service

    = retrofit.create(GitHubService.class);
  9. 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 */ );
  10. Integration with RxJava Retrofit retrofit = new Retrofit.Builder() .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create(gson))

    .baseUrl("https://api.github.com/") .build();
  11. Change Return Type public interface GitHubService { @GET("users/{user}/repos") Single<List<Repo>> listRepos(@Path("user")

    String user); }
  12. Subscribe Single<List<Repo>> repos = service.listRepos("srym") repos .subscribe( list -> doSomethingToList(list),

    throwable -> Timber.d(throwable.getMessage(), throwable), () -> Timber.d("complete") );
  13. Link • RxJava+RetrofitͰAPI௨৴पΓΛ࣮૷͢Δ͏͑ Ͱ࠷௿ݶͷ஌ࣝΛ30෼Ͱ٧ΊࠐΉ • http://qiita.com/FumihikoSHIROYAMA/ items/201536d9b45ef21b6bc7

  14. Link • RetrofitΛ࢖ͬͨOAuth࠶ೝূΞϓϩʔν • http://qiita.com/FumihikoSHIROYAMA/ items/ac1beaeaa9b4baaed939

  15. Link • RetrofitΛ࢖ͬͨAPIݺͼग़͠ͰϦΧόϦՄೳ ͳHTTPΤϥʔΛͲ͏ѻ͏͔໰୊ • http://qiita.com/FumihikoSHIROYAMA/ items/65d52aea1a9f324d347e

  16. What's Good about Retrofit + Rx • Easy to define

    • Easy to compose • Easy to test
  17. Test • MockWebServer • TestSubscriber

  18. MockWebServer • A scriptable web server for testing HTTP clients

    • https://github.com/square/okhttp/tree/ master/mockwebserver
  19. MockWebServer private final MockWebServer mockWebServer = new MockWebServer();

  20. MockWebServer Dispatcher dispatcher = new Dispatcher() { @Override public MockResponse

    dispatch(RecordedRequest request) throws InterruptedException { return new MockResponse().setResponseCode(404); } }; mockWebServer.setDispatcher(dispatcher); mockWebServer.start();
  21. 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); }
  22. MockWebServer Retrofit retrofit = new Retrofit.Builder() .baseUrl(mockWebServer.url("")) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .addConverterFactory(GsonConverterFactory.create()) .build();

    GitHubService gitHubService = retrofit.create(GitHubService.class);
  23. 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
  24. TestSubscriber restGitHubDataSource .listRepos("srym") .test();

  25. TestSubscriber List<Repo> repos = restGitHubDataSource.listRepos("srym") .test() .await() .assertNoErrors() .assertComplete() .values()

    .get(0); assertThat(repos).isNotNull();
  26. 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

  27. Easy to compose • Rx's Observable is easily & flexibly

    combined • Avoid callback hells
  28. 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); } }
  29. 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; }
  30. Easy to compose @Override public Single<List<RepoModel>> listRepos(@NonNull String user) {

    return remoteDataSource .listRepos(user) .map(mapper::convert);
  31. 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);
  32. Android Clean Architecture • android10/Android-CleanArchitecture • https://github.com/android10/Android- CleanArchitecture • srym/Architecture

    • https://github.com/srym/Architecture
  33. None