Kotlin + RxJava2 + Dagger2 + Orma
+ Retrofit2 で作るAndroidアプリ at DroidKaigi 2017

Kotlin + RxJava2 + Dagger2 + Orma
+ Retrofit2 で作るAndroidアプリ at DroidKaigi 2017

TwitterID変えました。@lvla0805 -> @MoyuruAizawa

このスライド内ではHTTP通信にObservableを利用していますが、HTTP通信は成功か失敗しかないので本来であればSingleを利用するほうが妥当です。
このスライドでは敷居をさげるためにStreamの説明をObservableだけにとどめました。

5f533179da1c82722252cbcb93e7356f?s=128

Moyuru Aizawa

March 10, 2017
Tweet

Transcript

  1. 4.

    Agenda ‣ Sample Application ‣ ٕज़֓ཁ ‣ Kotlin ‣ RxJava

    ‣ Retrofit ‣ Orma ‣ Sample ‣ Client ‣ Database ‣ Repository ‣ Activity ‣ Dagger2
  2. 9.

    ٕज़֓ཁ Languages Kotlin 1.1 Network Retrofit 2.1.0 OkHttp 3.6.0 O/R

    Mapper Orma 4.2.0 Reactive Programming RxJava 2.0.2 Dependency Injection Dagger 2.9
  3. 10.

    build.gradle(Ұ෦) apply plugin: 'kotlin-android' apply plugin: 'kotlin-kapt' android { dataBinding

    { enabled = true } } dependencies { // Databinding kapt 'com.android.databinding:compiler:2.3.0' // Orma compile "com.github.gfx.android.orma:orma:$ormaVersion" kapt "com.github.gfx.android.orma:orma-processor:$ormaVersion" // ReactiveX compile 'io.reactivex.rxjava2:rxjava:2.0.2' compile 'io.reactivex.rxjava2:rxandroid:2.0.1' // Retrofit compile "com.squareup.retrofit2:retrofit:$retrofitVersion" compile "com.squareup.retrofit2:converter-gson:$retrofitVersion" compile 'com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.0.0' compile "com.squareup.okhttp3:logging-interceptor:$okHttpVersion" // Dagger2 compile "com.google.dagger:dagger:$daggerVersion" kapt "com.google.dagger:dagger-compiler:$daggerVersion" }
  4. 11.
  5. 13.

    class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {

    … val message = "Clicked" button.setOnClickListener { textView.text = message } } } Kotlin
  6. 14.

    class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {

    … val message = "Clicked" button.setOnClickListener { textView.text = message } } } Kotlin
  7. 15.

    class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {

    … val message = "Clicked" button.setOnClickListener { textView.text = message } } } Kotlin
  8. 16.

    class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {

    … val message = "Clicked" button.setOnClickListener { textView.text = message } } } Kotlin
  9. 17.

    class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {

    … val message = "Clicked" button.setOnClickListener { textView.text = message } } } Kotlin
  10. 18.

    class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) {

    … val message = "Clicked" button.setOnClickListener { textView.text = message } } } Kotlin
  11. 19.
  12. 21.

    RxJava val observable = Observable.create<Int> { subscriber -> intArray.forEach {

    subscriber.onNext(it) } subscriber.onComplete() } observable.subscribe( { num -> println(num) }, { throwable -> throwable.printStackTrace() }, { println("onCompleted") })
  13. 22.

    RxJava val observable = Observable.create<Int> { subscriber -> intArray.forEach {

    subscriber.onNext(it) } subscriber.onComplete() } observable.subscribe( { num -> println(num) }, { throwable -> throwable.printStackTrace() }, { println("onCompleted") })
  14. 23.

    RxJava val observable = Observable.create<Int> { subscriber -> intArray.forEach {

    subscriber.onNext(it) } subscriber.onComplete() } observable.subscribe( { num -> println(num) }, { throwable -> throwable.printStackTrace() }, { println("onCompleted") })
  15. 24.

    RxJava val observable = Observable.create<Int> { subscriber -> intArray.forEach {

    subscriber.onNext(it) } subscriber.onComplete() } observable.subscribe( { num -> println(num) }, { throwable -> throwable.printStackTrace() }, { println("onCompleted") })
  16. 25.

    RxJava val observable = Observable.create<Int> { subscriber -> intArray.forEach {

    subscriber.onNext(it) } subscriber.onComplete() } observable.subscribe( { num -> println(num) }, { throwable -> throwable.printStackTrace() }, { println("onCompleted") })
  17. 26.

    RxJava val observable = Observable.create<Int> { subscriber -> intArray.forEach {

    subscriber.onNext(it) } subscriber.onComplete() } observable.subscribe( { num -> println(num) }, { throwable -> throwable.printStackTrace() }, { println("onCompleted") })
  18. 27.

    RxJava val observable = Observable.create<Int> { subscriber -> intArray.forEach {

    subscriber.onNext(it) } subscriber.onComplete() } observable.subscribe( { num -> println(num) }, { throwable -> throwable.printStackTrace() }, { println("onCompleted") })
  19. 28.

    RxJava val observable = Observable.create<Int> { subscriber -> intArray.forEach {

    subscriber.onNext(it) } subscriber.onComplete() } observable.subscribe( { num -> println(num) }, { throwable -> throwable.printStackTrace() }, { println("onCompleted") })
  20. 29.

    RxJava val observable = Observable.create<Int> { subscriber -> intArray.forEach {

    subscriber.onNext(it) } subscriber.onComplete() } observable.subscribe( { num -> println(num) }, { throwable -> throwable.printStackTrace() }, { println("onCompleted") })
  21. 35.
  22. 44.
  23. 53.
  24. 56.

    Orma @Table data class Contributor( @PrimaryKey(auto = false) @Setter("name") val

    name: String, @Column @Setter("avatarUrl") val avatarUrl: String?, @Column @Setter("htmlUrl") val htmlUrl: String?, @Column @Setter("contributions") val contributions: Int )
  25. 57.

    Orma @Table data class Contributor( @PrimaryKey(auto = false) @Setter("name") val

    name: String, @Column @Setter("avatarUrl") val avatarUrl: String?, @Column @Setter("htmlUrl") val htmlUrl: String?, @Column @Setter("contributions") val contributions: Int )
  26. 58.

    Orma @Table data class Contributor( @PrimaryKey(auto = false) @Setter("name") val

    name: String, @Column @Setter("avatarUrl") val avatarUrl: String?, @Column @Setter("htmlUrl") val htmlUrl: String?, @Column @Setter("contributions") val contributions: Int )
  27. 59.

    Orma @Table data class Contributor( @PrimaryKey(auto = false) @Setter("name") val

    name: String, @Column @Setter("avatarUrl") val avatarUrl: String?, @Column @Setter("htmlUrl") val htmlUrl: String?, @Column @Setter("contributions") val contributions: Int )
  28. 64.
  29. 70.
  30. 71.
  31. 72.
  32. 73.
  33. 74.

    Dao

  34. 75.

    Dao class ContributorDao(orma: OrmaDatabase) { fun insert(contributors: List<Contributor>) { orma.transactionSync

    { orma.prepareInsertIntoContributor(OnConflict.REPLACE) .executeAll(contributors) } } fun findAll(): List<Contributor> { return orma.selectFromContributor() .executeAsObservable() .toList() } }
  35. 76.

    Dao class ContributorDao(orma: OrmaDatabase) { fun insert(contributors: List<Contributor>) { orma.transactionSync

    { orma.prepareInsertIntoContributor(OnConflict.REPLACE) .executeAll(contributors) } } fun findAll(): List<Contributor> { return orma.selectFromContributor() .executeAsObservable() .toList() } }
  36. 77.

    Dao class ContributorDao(orma: OrmaDatabase) { fun insert(contributors: List<Contributor>) { orma.transactionSync

    { orma.prepareInsertIntoContributor(OnConflict.REPLACE) .executeAll(contributors) } } fun findAll(): List<Contributor> { return orma.selectFromContributor() .executeAsObservable() .toList() } }
  37. 79.

    Repository class ContributorRepository( private val client: GitHubClient, private val dao:

    ContributorDao) { fun getContributors(): Observable<List<Contributor>> { return client.fetchContributors() .doOnNext { list -> dao.insert(list) } .onErrorReturn { dao.findAll() } } }
  38. 80.

    Repository class ContributorRepository( private val client: GitHubClient, private val dao:

    ContributorDao) { fun getContributors(): Observable<List<Contributor>> { return client.fetchContributors() .doOnNext { list -> dao.insert(list) } .onErrorReturn { dao.findAll() } } }
  39. 81.

    Repository class ContributorRepository( private val client: GitHubClient, private val dao:

    ContributorDao) { fun getContributors(): Observable<List<Contributor>> { return client.fetchContributors() .doOnNext { list -> dao.insert(list) } .onErrorReturn { dao.findAll() } } }
  40. 82.

    Repository class ContributorRepository( private val client: GitHubClient, private val dao:

    ContributorDao) { fun getContributors(): Observable<List<Contributor>> { return client.fetchContributors() .doOnNext { list -> dao.insert(list) } .onErrorReturn { dao.findAll() } } }
  41. 83.
  42. 84.

    Activity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val retrofit = Retrofit.Builder().......build() val orma = OrmaDatabase.builder(context).......build() val service = retrofit.create(GitHubService::class.java) val client = ContributorClient(service) val dao = ContributorDao(orma) val repository = ContributorRepository(client, dao) repository.getContributors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { contributors -> showContributors(contributors) }, { Timber.e(it, "getContributors") } ) } }
  43. 85.

    Activity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val retrofit = Retrofit.Builder().......build() val orma = OrmaDatabase.builder(context).......build() val service = retrofit.create(GitHubService::class.java) val client = ContributorClient(service) val dao = ContributorDao(orma) val repository = ContributorRepository(client, dao) repository.getContributors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { contributors -> showContributors(contributors) }, { Timber.e(it, "getContributors") } ) } }
  44. 86.

    Activity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val retrofit = Retrofit.Builder().......build() val orma = OrmaDatabase.builder(context).......build() val service = retrofit.create(GitHubService::class.java) val client = ContributorClient(service) val dao = ContributorDao(orma) val repository = ContributorRepository(client, dao) repository.getContributors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { contributors -> showContributors(contributors) }, { Timber.e(it, "getContributors") } ) } }
  45. 87.

    Activity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val retrofit = Retrofit.Builder().......build() val orma = OrmaDatabase.builder(context).......build() val service = retrofit.create(GitHubService::class.java) val client = ContributorClient(service) val dao = ContributorDao(orma) val repository = ContributorRepository(client, dao) repository.getContributors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { contributors -> showContributors(contributors) }, { Timber.e(it, "getContributors") } ) } }
  46. 88.

    Activity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val retrofit = Retrofit.Builder().......build() val orma = OrmaDatabase.builder(context).......build() val service = retrofit.create(GitHubService::class.java) val client = ContributorClient(service) val dao = ContributorDao(orma) val repository = ContributorRepository(client, dao) repository.getContributors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { contributors -> showContributors(contributors) }, { Timber.e(it, "getContributors") } ) } }
  47. 89.

    Activity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val retrofit = Retrofit.Builder().......build() val orma = OrmaDatabase.builder(context).......build() val service = retrofit.create(GitHubService::class.java) val client = ContributorClient(service) val dao = ContributorDao(orma) val repository = ContributorRepository(client, dao) repository.getContributors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { contributors -> showContributors(contributors) }, { Timber.e(it, "getContributors") } ) } }
  48. 90.

    Activity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val retrofit = Retrofit.Builder().......build() val orma = OrmaDatabase.builder(context).......build() val service = retrofit.create(GitHubService::class.java) val client = ContributorClient(service) val dao = ContributorDao(orma) val repository = ContributorRepository(client, dao) repository.getContributors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { contributors -> showContributors(contributors) }, { Timber.e(it, "getContributors") } ) } }
  49. 91.

    Activity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val retrofit = Retrofit.Builder().......build() val orma = OrmaDatabase.builder(context).......build() val service = retrofit.create(GitHubService::class.java) val client = ContributorClient(service) val dao = ContributorDao(orma) val repository = ContributorRepository(client, dao) repository.getContributors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { contributors -> showContributors(contributors) }, { Timber.e(it, "getContributors") } ) } }
  50. 92.

    Activity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val retrofit = Retrofit.Builder().......build() val orma = OrmaDatabase.builder(context).......build() val service = retrofit.create(GitHubService::class.java) val client = ContributorClient(service) val dao = ContributorDao(orma) val repository = ContributorRepository(client, dao) repository.getContributors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { contributors -> showContributors(contributors) }, { Timber.e(it, "getContributors") } ) } }
  51. 93.

    Activity class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val retrofit = Retrofit.Builder().......build() val orma = OrmaDatabase.builder(context).......build() val service = retrofit.create(GitHubService::class.java) val client = ContributorClient(service) val dao = ContributorDao(orma) val repository = ContributorRepository(client, dao) repository.getContributors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { contributors -> showContributors(contributors) }, { Timber.e(it, "getContributors") } ) } }
  52. 95.
  53. 99.

    Module @Module class ApplicationModule(private val applicationContext: App) { @Provides fun

    provideContext(): Context {…} @Provides fun provideOkHttp(): OkHttpClient {…} @Provides fun provideRetrofit(o: OkHttpClient): Retrofit {…} @Provides fun provideOrma(c: Context): OrmaHolder {…} @Provides fun provide…Dao(oh: OrmaHolder): ContributorDao {…} @Provides fun provideGitHubService(r: Retrofit): GitHubService {…} @Provides fun provideGitHubClient(s: GitHubService): GitHubClient {…} }
  54. 100.

    Module @Module class ApplicationModule(private val applicationContext: App) { @Provides fun

    provideContext(): Context {…} @Provides fun provideOkHttp(): OkHttpClient {…} @Provides fun provideRetrofit(o: OkHttpClient): Retrofit {…} @Provides fun provideOrma(c: Context): OrmaHolder {…} @Provides fun provide…Dao(oh: OrmaHolder): ContributorDao {…} @Provides fun provideGitHubService(r: Retrofit): GitHubService {…} @Provides fun provideGitHubClient(s: GitHubService): GitHubClient {…} }
  55. 101.

    Module @Module class ApplicationModule(private val applicationContext: App) { @Provides fun

    provideContext(): Context {…} @Provides fun provideOkHttp(): OkHttpClient {…} @Provides fun provideRetrofit(o: OkHttpClient): Retrofit {…} @Provides fun provideOrma(c: Context): OrmaHolder {…} @Provides fun provide…Dao(oh: OrmaHolder): ContributorDao {…} @Provides fun provideGitHubService(r: Retrofit): GitHubService {…} @Provides fun provideGitHubClient(s: GitHubService): GitHubClient {…} }
  56. 102.

    Module @Module class ApplicationModule(private val applicationContext: App) { @Provides fun

    provideContext(): Context {…} @Provides fun provideOkHttp(): OkHttpClient {…} @Provides fun provideRetrofit(o: OkHttpClient): Retrofit {…} @Provides fun provideOrma(c: Context): OrmaHolder {…} @Provides fun provide…Dao(oh: OrmaHolder): ContributorDao {…} @Provides fun provideGitHubService(r: Retrofit): GitHubService {…} @Provides fun provideGitHubClient(s: GitHubService): GitHubClient {…} }
  57. 103.

    TIPS @Module class ApplicationModule(private val applicationContext: App) { @Provides fun

    provideContext(): Context {…} @Provides fun provideOkHttp(): OkHttpClient {…} @Provides fun provideRetrofit(o: OkHttpClient): Retrofit {…} @Provides fun provideOrma(c: Context): OrmaHolder {…} @Provides fun provide…Dao(oh: OrmaHolder): ContributorDao {…} @Provides fun provideGitHubService(r: Retrofit): GitHubService {…} @Provides fun provideGitHubClient(s: GitHubService): GitHubClient {…} }
  58. 116.

    Application class class App : Application() { lateinit var component:

    ApplicationComponent override fun onCreate() { component = DaggerApplicationComponent.builder() .applicationModule(ApplicationModule(this)) .build() } }
  59. 117.

    Application class class App : Application() { lateinit var component:

    ApplicationComponent override fun onCreate() { component = DaggerApplicationComponent.builder() .applicationModule(ApplicationModule(this)) .build() } }
  60. 118.

    Application class class App : Application() { lateinit var component:

    ApplicationComponent override fun onCreate() { component = DaggerApplicationComponent.builder() .applicationModule(ApplicationModule(this)) .build() } }
  61. 119.

    Application class class App : Application() { lateinit var component:

    ApplicationComponent override fun onCreate() { component = DaggerApplicationComponent.builder() .applicationModule(ApplicationModule(this)) .build() } }
  62. 120.

    Application class class App : Application() { lateinit var component:

    ApplicationComponent override fun onCreate() { component = DaggerApplicationComponent.builder() .applicationModule(ApplicationModule(this)) .build() } }
  63. 121.

    Application class class App : Application() { lateinit var component:

    ApplicationComponent override fun onCreate() { component = DaggerApplicationComponent.builder() .applicationModule(ApplicationModule(this)) .build() } }
  64. 122.

    Application class class App : Application() { val component: ApplicationComponent

    by lazy { DaggerApplicationComponent.builder() .applicationModule(ApplicationModule(this)) .build() } }
  65. 123.

    MainActivity class MainActivity : AppCompatActivity() { @Inject lateinit var repository:

    ContributorRepository override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (application as App).component.inject(this) repository.getContributors().... } }
  66. 124.

    MainActivity class MainActivity : AppCompatActivity() { @Inject lateinit var repository:

    ContributorRepository override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (application as App).component.inject(this) repository.getContributors().... } }
  67. 125.

    MainActivity class MainActivity : AppCompatActivity() { @Inject lateinit var repository:

    ContributorRepository override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (application as App).component.inject(this) repository.getContributors().... } }
  68. 126.

    Before class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?)

    { super.onCreate(savedInstanceState) val retrofit = Retrofit.Builder().......build() val orma = OrmaDatabase.builder(context).......build() val service = retrofit.create(GitHubService::class.java) val client = ContributorClient(service) val dao = ContributorDao(orma) val repository = ContributorRepository(client, dao) repository.getContributors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { contributors -> showContributors(contributors) }, { Timber.e(it, "getContributors") } ) } }
  69. 127.

    After class MainActivity : AppCompatActivity() { @Inject lateinit var repository:

    ContributorRepository override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) (application as App).component.inject(this) repository.getContributors() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { contributors -> showContributors(contributors) }, { Timber.e(it, "getContributors") } ) } }
  70. 128.
  71. 130.