Kotlin + Architecture Component + Dagger2によるAndroidアプリ設計

# はじめに

Google I/O 2017でKotlinがAndroidアプリ開発における[公式言語としてサポート](https://blog.jetbrains.com/kotlin/2017/05/kotlin-on-android-now-official/)されることになりました。
また、同時に[Android Architecture Components](https://developer.android.com/topic/libraries/architecture/index.html)がAndroidのライフサイクルにおける画面回転などへの対応を容易にするライブラリとして追加され、このライブラリを用いた[Androidアプリ開発におけるおすすめの設計](https://developer.android.com/topic/libraries/architecture/guide.html#recommended_app_architecture)が提案されています。
以下のGoogleのSampleリポジトリにはその設計指針を用いたサンプルが公開されています。

https://github.com/googlesamples/android-architecture-components/tree/master/GithubBrowserSample

本記事では上記のリポジトリを参考にしながら、KotlinとArchitecture Components、そしてDagger2を用いた設計を備忘録的にまとめました。
また、現在進行系で開発しているので、何か間違っている点やご意見等あればぜひ、コメントや[Twitter](https://twitter.com/satorufujiwara)などでお願いします。

# Sample

記事における実装のサンプルは以下にあります。

https://github.com/satorufujiwara/kotlin-architecture-components

Android Studio3.0 Canary3以降でビルド可能です。

# 実装について

## Kotlin

Kotlinについては私も執筆に参加させて頂いた[「Kotlin入門までの助走読本」](http://goo.gl/5vUT7o)(PDF注意)を読んで頂くのが良いかと思います。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">豪華執筆陣による「Kotlin入門までの助走読本」をリリースします！<br>話題のプログラミング言語の「味見」をぜひ！PDF注意<a href="https://t.co/LJJDReAzue">https://t.co/LJJDReAzue</a></p>&mdash; 日本Kotlinユーザグループ (@kotlin_jp) <a href="https://twitter.com/kotlin_jp/status/869003897825705984">2017年5月29日</a></blockquote>
<script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>

またGoogle I/O 2017のセッションの中でIntroduction to KotlinというKotlinを知って頂く上でおすすめのセッションがあり、そちらを翻訳した記事がありますのであわせてご覧ください。

- [Google I/O 2017 : Introduction to Kotlin (和訳/要約)](http://qiita.com/satorufujiwara/items/490c1499acec1a921258)

### build.gradle

Kotlinはbuild.gradleに以下のような記述を追加することで使うことが出来ます。

```kotlin:build.gradle
buildscript {
    ext.kotlin_version = '1.1.2-4'
    dependencies {
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}
```
```kotlin:app/build.gradle
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-kapt'

//...
dependencies {
    // kotlin
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
}
```
Architecture ComponentsやDagger2といったライブラリがAnnotations Processingを用いてますので、Kotlin用の`kotlin-kapt`も忘れずに導入します。
今回は`kotlin-stdlib-jre7`を用いてますが、[こちらの記事](http://qiita.com/kubode/items/b87f3a3cc1abc1616423#appbuildgradle)によるとminSdkVersion<19では`kotlin-stdlib`を用いたほうが良さそうです。

### Moshi

JSONのパーサーとしては[Gson](https://github.com/google/gson)が有名ですが、今回は[Moshi](https://github.com/square/moshi)を用いました。
理由として、Moshiには[Kotinサポート](https://medium.com/square-corner-blog/kotlins-a-great-language-for-json-fcd6ef99256b)が入っています。
特にKotlinのNon-Nullなpropertyの扱いがGsonだと良くないため、Moshiをおすすめします。
上記に関しては[こちらの記事](http://qiita.com/egugue/items/f1f35c250f7a25768751
)に詳しく解説されています。

MoshiとMoshiのkotlinサポートは以下のように導入します。

```kotlin:app/build.gradle
dependencies {
    implementation "com.squareup.moshi:moshi:$moshi_version"
    implementation "com.squareup.moshi:moshi-kotlin:$moshi_version"
}
```

Moshiインスタンスを初期化する時に、`KotlinJsonAdapterFactory`を用い、またRetrofitの`ConverterFactory`として`MoshiConverterFactory`を指定します。

```kotlin:.data.di.DataModule.kt
@Module
class DataModule {

  @Singleton @Provides
  fun provideMoshi() = Moshi.Builder()
      .add(KotlinJsonAdapterFactory())
      .build()

  @Singleton @Provides
  fun provideRetrofit(oktHttpClient: OkHttpClient, moshi: Moshi): Retrofit
      = Retrofit.Builder()
      .client(oktHttpClient)
      .baseUrl("https://api.github.com")
      .addConverterFactory(MoshiConverterFactory.create(moshi))
      .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
      .build()
}
```

### Databinding

DataBindingとKotlinを合わせて使うためには、`com.android.databinding:compiler`を導入する必要があります。
ライブラリの最新バージョンは[こちら](https://bintray.com/android/android-tools/com.android.databinding.compiler)でチェックすることが出来ます。

```kotlin:app/build.gradle
android {
    //...
    dataBinding {
        enabled = true
    }
}

dependencies {
    kapt "com.android.databinding:compiler:2.3.3"
}
```

## Architecture Components

Architecture Componentsを導入するにはbuild.gradleに以下のように記述します。

```kotlin:app/build.gradle
dependencies {
    // architecture components
    implementation "android.arch.lifecycle:runtime:$arch_version"
    implementation "android.arch.lifecycle:extensions:$arch_version"
    implementation "android.arch.lifecycle:reactivestreams:$arch_version"
    kapt "android.arch.lifecycle:compiler:$arch_version"
}
```

今回はRetrofitのレスポンスをRxJavaの`Flowable`で受け取っているため、そちらを`LiveData`に変換するためのライブラリ`android.arch.lifecycle:reactivestreams`も合わせて導入しています。
[このサンプル](https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/main/java/com/android/example/github/util/LiveDataCallAdapterFactory.java)のようにRetrofitの`CallAdapterFactory`として`LiveData`に変換するためのクラスを用意すれば、Retrofitのレスポンスをそのまま`LiveData`に変換することも出来ます。
RxJavaへの依存をしたくない場合などはこちらが良いでしょう。

### ViewModel

Architecture Componentsを導入する場合のアプリの設計は以下のようになります。
[出典:Guide to App Architecture](https://developer.android.com/topic/libraries/architecture/guide.html#the_final_architecture)

![final-architecture.png](https://qiita-image-store.s3.amazonaws.com/0/36413/9cdd5c86-b231-aa42-490e-7e60ce5e771e.png)

```kotlin:.ui.main.MainViewModel.kt
class MainViewModel @Inject constructor(private val repository: GitHubRepository) : ViewModel() {

  val ownerId = MutableLiveData<String>()
  val repos: LiveData<List<Repo>>

  init {
    repos = ownerId.switchMap {
      if (it.isEmpty()) AbsentLiveData.create()
      else repository.loadRepos(it)
          .subscribeOn(Schedulers.io())
          .observeOn(AndroidSchedulers.mainThread())
          .onErrorResumeNext(Flowable.empty())
          .toLiveData()
    }
  }

}
```

`ViewModel`として上記の`MainViewModel`クラスに`MutableLiveData`として`ownerId`と、`LiveData`としてreposの2つのプロパティを定義してあります。

`switchMap()`は`android.arch.lifecycle.Transformations`クラス内に定義されているJavaのstatic methodですが、以下のようにKotlinの拡張関数で呼び出せるようにしてあります。

```kotlin:.util.ext.ArchitectureComponentsExt.kt
fun <X, Y> LiveData<X>.switchMap(func: (X) -> LiveData<Y>)
    = Transformations.switchMap(this, func)
```
同様に`android.arch.lifecycle:reactivestreams`にはRxJavaの`Flowable`を`LiveData`に変換するためのstatic methodである`fromPublisher()`が定義されているので、同様にKotlinの拡張関数で呼び出せるようにしてあります。

```kotlin:.util.ext.LiveDataReactiveStreamsExt.kt
fun <T> Publisher<T>.toLiveData() = LiveDataReactiveStreams.fromPublisher(this)
```

以上のようにして、`ownerId`(の中身)が変更された時に(空でなければ)、`GitHubRepository.loadRepos() : Flowable`が呼ばれ、`repos`(の中身)が変更されます。

```kotlin:.ui.main.MainFragment.kt
class MainFragment : Fragment(), LifecycleRegistryOwner, Injectable {

  @Inject lateinit var viewModelFactory: ViewModelProvider.Factory
  private val viewModel by lazy { ViewModelProviders.of(activity, viewModelFactory).get(MainViewModel::class.java) }
  private val binding by lazy { DataBindingUtil.setContentView<MainFragmentBinding>(activity, R.layout.main_fragment) }
  private val lifecycleRegistry by lazy { LifecycleRegistry(this) }
  private val adapter = MainAdapter()

  override fun getLifecycle() = lifecycleRegistry

  override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    binding.recyclerView.adapter = adapter
    binding.recyclerView.layoutManager = LinearLayoutManager(activity)

    viewModel.repos.observe(this) {
      it ?: return@observe
      adapter.run {
        items.clear()
        items.addAll(it)
        notifyDataSetChanged()
      }
    }
    viewModel.ownerId.value = "satorufujiwara"
  }
}
```
MainFragmentからは`MainViewModel.repos`を`observe`し、その内容に応じてRecyclerViewに反映しています。

`MainViewModel`のインスタンスは`ViewModelProviders.of().get()`によって提供され、`ViewModelProvider.Factory`のインスタンスは後述するDaggerによってInjectされています。

Fragment上でviewModelのインスタンスを取る際に、`ViewModelProviders.of()`の第一引数に`Fragment.activity`(Javaでは`getActivity()`)を与えることによって親となるActivityや同じActivityに乗る他のFragmentとインスタンスを共通化出来ます。
こちらについては以下に詳細が書かれています。

- [Architecture Components > ViewModel > Sharing Data Between Fragments](https://developer.android.com/topic/libraries/architecture/viewmodel.html#sharing_data_between_fragments)

## Dagger2

Dagger2を導入するにはbuild.gradleに以下のように記述します。

```kotlin:app/build.gradle
dependencies {
    // dagger
    implementation "com.google.dagger:dagger:$dagger_version"
    implementation "com.google.dagger:dagger-android:$dagger_version"
    implementation "com.google.dagger:dagger-android-support:$dagger_version"
    kapt "com.google.dagger:dagger-compiler:$dagger_version"
    kapt "com.google.dagger:dagger-android-processor:$dagger_version"
}
```
Dagger2のバージョンは[2.11](https://github.com/google/dagger/releases/tag/dagger-2.11)でDagger2の2.10から追加された[dagger.android](https://google.github.io/dagger//android.html)を利用しています。

Dagger2はActivityやFragmentにRepositoryや`ViewModelProvider.Factory`といったArchitecture Componentsの要素となるクラスのインスタンスをInjectする用途に用いています。

### ActivityへのInject

ActivityへのInjectはdagger.android内にある[`AndroidInjectionModule`クラス](https://google.github.io/dagger/api/latest/dagger/android/AndroidInjectionModule.html)をアプリのComponentのmoduleとして以下のように指定します。
今回はSupport Library内にある`android.support.v4.app.Fragment`へのInjectを利用するため、`AndroidSupportInjectionModule`クラスを代わりに使用しています。

`Application`クラスへのInjectに対応するため`AppComponent`は`AndroidInjector<Application>`を継承しています。


```kotlin:di.AppComponent.kt
@Singleton
@Component(modules = arrayOf(
    AndroidSupportInjectionModule::class,
    AppModule::class,
    ActivityModule::class)
)
interface AppComponent : AndroidInjector<App> {

  @Component.Builder
  interface Builder {
    @BindsInstance fun application(application: App): Builder
    fun build(): AppComponent
  }

  override fun inject(app: App)
}

```

```kotlin:.di.ActivityModule.kt
@Module
internal abstract class ActivityModule {

  //...

  @ContributesAndroidInjector(modules = arrayOf(MainModule::class))
  internal abstract fun contributeMainActivity(): MainActivity

}
```
Activityを継承した`MainActivity`へのInjectは[`@ContributesAndroidInjector`アノテーション](https://google.github.io/dagger/api/latest/dagger/android/ContributesAndroidInjector.html)を用いて上記のように記述することによって、`MainActivity`内の必要な依存性を解決するためのコードが以下のように生成されます。

```java:.di.DaggerAppComponent.java(Daggerによって生成される)

public final class DaggerAppComponent implements AppComponent {

private Provider<
          Map<Class<? extends Activity>, Provider<AndroidInjector.Factory<? extends Activity>>>>
  private Provider<DispatchingAndroidInjector<Activity>> dispatchingAndroidInjectorProvider;

  private void initialize(final Builder builder) {

    this.mainActivitySubcomponentBuilderProvider =
        new dagger.internal.Factory<
            ActivityModule_ContributeMainActivity$app_debug.MainActivitySubcomponent.Builder>() {
          @Override
          public ActivityModule_ContributeMainActivity$app_debug.MainActivitySubcomponent.Builder
              get() {
            return new MainActivitySubcomponentBuilder();
          }
        };

    this.bindAndroidInjectorFactoryProvider = (Provider) mainActivitySubcomponentBuilderProvider;

      mapOfClassOfAndProviderOfFactoryOfProvider;
    this.mapOfClassOfAndProviderOfFactoryOfProvider =
        MapProviderFactory
            .<Class<? extends Activity>, AndroidInjector.Factory<? extends Activity>>builder(1)
            .put(MainActivity.class, bindAndroidInjectorFactoryProvider)
            .build();

    this.dispatchingAndroidInjectorProvider =
        DispatchingAndroidInjector_Factory.create(mapOfClassOfAndProviderOfFactoryOfProvider);
    //...
  }
}
```

上記コード内に出てくる`DispatchingAndroidInjector<Activity>`を保持するために`Application`クラスが[`HasActivityInjector`インタフェース](https://google.github.io/dagger/api/latest/dagger/android/HasActivityInjector.html)を実装する必要があります。

今回は既に`HasActivityInjector`の実装がなされている[`DaggerApplication`クラス](https://google.github.io/dagger/api/latest/dagger/android/support/DaggerApplication.html)を継承して実装しています。
このクラスは同名のクラスが`dagger.android.DaggerApplication`と`dagger.android.support.DaggerApplication`の2つ用意されているので注意が必要です。
今回はSupport Libraryに対応した後者のクラスを継承しています。

```kotlin:App.kt
class App : DaggerApplication() {

  override fun applicationInjector() = DaggerAppComponent.builder()
      .application(this)
      .build()

  override fun onCreate() {
    super.onCreate()
    applyAutoInjector()
  }

}
```

`DaggerApplication`は以下のように`AndroidInjector<? extends DaggerApplication>`を返すabstract methodを持ってますので、`DaggerAppComponent`を`build()`して実装します。

```java:dagger.android.support.DaggerApplication.java
public abstract class DaggerApplication extends dagger.android.DaggerApplication implements HasSupportFragmentInjector {
  @Inject
  DispatchingAndroidInjector<Fragment> supportFragmentInjector;

  public DaggerApplication() {
  }

  protected abstract AndroidInjector<? extends DaggerApplication> applicationInjector();

  public DispatchingAndroidInjector<Fragment> supportFragmentInjector() {
    return this.supportFragmentInjector;
  }
}
```

以上のようにすることで、`MainActivity.onCreate()`内で`AndroidInjection.inject(this)`を呼出すことで必要なInjectが出来ます。

今回は以下のような`Application.ActivityLifecycleCallbacks`を登録する拡張関数用いて、`Injectable`インタフェースを実装したクラス内においては`AndroidInjection.inject(this)`の記述を不要にしています。

```kotlin:.di.AutoInjector.kt
interface Injectable

fun Application.applyAutoInjector() = registerActivityLifecycleCallbacks(
    object : Application.ActivityLifecycleCallbacks {

      override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
        handleActivity(activity)
      }

      override fun onActivityStarted(activity: Activity) {

      }

      override fun onActivityResumed(activity: Activity) {

      }

      override fun onActivityPaused(activity: Activity) {

      }

      override fun onActivityStopped(activity: Activity) {

      }

      override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle?) {

      }

      override fun onActivityDestroyed(activity: Activity) {

      }
    })

private fun handleActivity(activity: Activity) {
  if (activity is Injectable || activity is HasSupportFragmentInjector) {
    AndroidInjection.inject(activity)
  }
  if (activity is FragmentActivity) {
    activity.supportFragmentManager.registerFragmentLifecycleCallbacks(
        object : FragmentManager.FragmentLifecycleCallbacks() {
          override fun onFragmentCreated(fm: FragmentManager, f: Fragment, s: Bundle?) {
            if (f is Injectable) {
              AndroidSupportInjection.inject(f)
            }
          }
        }, true)
  }
}
```

### FragmentへのInject

FragmentへのInjectはActivityと同様に`@ContributesAndroidInjector`アノテーションを用いて記述することで必要なコードが生成されます。

```kotlin:.ui.main.di.MainModule.kt
@Module
internal abstract class MainModule {

  //...

  @ContributesAndroidInjector
  abstract fun contributeMainFragment(): MainFragment

}
```

親となるActivityは[`HasSupportFragmentInjector`インタフェース](https://google.github.io/dagger/api/latest/dagger/android/support/HasSupportFragmentInjector.html)を実装し、`DispatchingAndroidInjector<Fragment>`クラスを保持する必要があります。
このクラスのインスタンスは上記コードにより必要なコードが生成されているので、DaggerによってInject出来ます。

```kotlin:.ui.main.MainActivity.kt
class MainActivity : AppCompatActivity(), LifecycleRegistryOwner, HasSupportFragmentInjector {

  @Inject lateinit var androidInjector: DispatchingAndroidInjector<Fragment>

  override fun supportFragmentInjector() = androidInjector

  //...
}

```

### ViewModelのInject

ViewModelのインスタンスはArchitecture Componentの`ViewModelProviders`によって管理、提供されますが、その際に必要な`ViewModelProvider.Factory`はDaggerによってそのインスタンスをInjectします。

```kotlin:.di.ActivityModule
@Module
internal abstract class ActivityModule {

  @Binds
  abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory

  //...
}
```
上記のように記述し、実体となる`ViewModelFactory`クラスを以下のように定義します。

```kotlin:.di.ViewModelFactory.kt
class ViewModelFactory @Inject
constructor(private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>)
  : ViewModelProvider.Factory {

  @Suppress("UNCHECKED_CAST")
  override fun <T : ViewModel> create(modelClass: Class<T>): T {
    var creator: Provider<ViewModel>? = creators[modelClass]
    if (creator == null) {
      for ((key, value) in creators) {
        if (modelClass.isAssignableFrom(key)) {
          creator = value
          break
        }
      }
    }
    if (creator == null) throw IllegalArgumentException("unknown model class " + modelClass)
    try {
      return creator.get() as T
    } catch (e: Exception) {
      throw RuntimeException(e)
    }
  }
}
```

引数となる

```kotlin
private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
```
へは`@Inject`インタフェースを用いてDaggerによってInjectします。

```kotlin:.di.ViewModelKey.kt
import android.arch.lifecycle.ViewModel
import dagger.MapKey
import kotlin.reflect.KClass

@MustBeDocumented
@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
@MapKey
internal annotation class ViewModelKey(val value: KClass<out ViewModel>)
```

```kotlin:.ui.main.di.MainModule.kt
@Module
internal abstract class MainModule {

  @Binds
  @IntoMap
  @ViewModelKey(MainViewModel::class)
  abstract fun bindMainViewModel(viewModel: MainViewModel): ViewModel

  //...

}
```

上記のように記述することで、Daggerの[Multibindings](https://google.github.io/dagger//multibindings.html)の機能を用いて、`creators`にInjectするための`Map<Class<? extends ViewModel>, Provider<ViewModel>>`(Javaでの記述)クラスをInjectするためのコードが以下のように生成されます。
`ViewModelKey`アノテーションを定義する際はKotlinのアノテーションを利用しています(Javaだと[このサンプルのような記述](https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/src/main/java/com/android/example/github/di/ViewModelKey.java)になります)。

```java:.di.DaggerAppComponent.java(Daggerによって生成される)

public final class DaggerAppComponent implements AppComponent {
  //...
private final class MainActivitySubcomponentImpl
      implements ActivityModule_ContributeMainActivity$app_debug.MainActivitySubcomponent {

    private Provider<Map<Class<? extends ViewModel>, Provider<ViewModel>>>
        mapOfClassOfAndProviderOfViewModelProvider;
    private Provider<ViewModelFactory> viewModelFactoryProvider;
    private Provider<ViewModelProvider.Factory> bindViewModelFactoryProvider;

    private void initialize(final MainActivitySubcomponentBuilder builder) {
      //...

      this.bindMainViewModelProvider = (Provider) mainViewModelProvider;

      this.mapOfClassOfAndProviderOfViewModelProvider =
          MapProviderFactory.<Class<? extends ViewModel>, ViewModel>builder(1)
              .put(MainViewModel.class, bindMainViewModelProvider)
              .build();

      this.viewModelFactoryProvider =
          ViewModelFactory_Factory.create(mapOfClassOfAndProviderOfViewModelProvider);

      this.bindViewModelFactoryProvider = (Provider) viewModelFactoryProvider;

    }
```
```kotlin
private val creators: Map<Class<out ViewModel>, @JvmSuppressWildcards Provider<ViewModel>>
```

`creators`を上記のように`@JvmSuppressWildcards`を用いずに定義すると、Kotlinはコンパイル時に`creators`の型を以下のようなクラスと解釈し、DaggerによるInjectが行えないので注意が必要です。

```java
java.util.Map<java.lang.Class<? extends android.arch.lifecycle.ViewModel>,? extends javax.inject.Provider<android.arch.lifecycle.ViewModel>>
```

### ActivityModuleとMainModule

```kotlin:.di.ActivityModule
@Module
internal abstract class ActivityModule {

  @Binds
  abstract fun bindViewModelFactory(factory: ViewModelFactory): ViewModelProvider.Factory

  @ContributesAndroidInjector(modules = arrayOf(MainModule::class))
  internal abstract fun contributeMainActivity(): MainActivity

}
```

```kotlin:.ui.main.di.MainModule.kt
@Module
internal abstract class MainModule {

  @Binds
  @IntoMap
  @ViewModelKey(MainViewModel::class)
  abstract fun bindMainViewModel(viewModel: MainViewModel): ViewModel

  @ContributesAndroidInjector
  abstract fun contributeMainFragment(): MainFragment

}
```

`ActivityModule`と`MainModule`の実装は全体で以上のようになります。
アプリ内にActivityが増えるたびに`ActivityModule`内に、Activityとそれに対応するModuleの対応の記述が増え、Activity内にFragmentやViewModelが増えるたびに対応するModule内(`MainModule`など)に記述が増えるような実装にしました。

## pacakge構成

最後に全体のフォルダ構成(debug時)を記載します。

<img width="404" alt="app-packages.png" src="https://qiita-image-store.s3.amazonaws.com/0/36413/813dc68c-0b0e-5a4b-380b-49af368fa1a0.png">

# まとめ

いくつか注意点は必要ですが、KotlinとArchitecture ComponentsそしてDagger2による実装は問題なく行えるように感じました。
Architecture ComponentsによってActivity/Fragmentのライフサイクルが考慮されているので、`savedInstanceState`まわりの記述が不要になるのはとても大きなメリットです。
また、[RxLifecycle](https://github.com/trello/RxLifecycle)を用いることでLiveDataの代わりにRxJavaを用いることも可能そうです。

Architecture Componentsの正式リリースを待つことにはなりますが、現在開発中のアプリでは以上のような実装にしたいと考えています。
コメントや[Twitter](https://twitter.com/satorufujiwara)や[GitHub](https://github.com/satorufujiwara/kotlin-architecture-components)へ、フィードバックお待ちしています！