Kotlin を学ぶ際に、まずは通信周りを勉強したので、そこで得た知識を記事にしました。
Dagger2 + Retrofit2 + Moshi
Dagger2 + Retrofit2 + Moshi を導入する。
buildscript {
ext.kotlin_version = '1.3.11'
ext.dagger_version = '2.19'
ext.retrofit_version = '2.5.0'
ext.moshi_version = '1.8.0'
...
apply plugin: 'kotlin-kapt'
...
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
...
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"
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
implementation "com.squareup.retrofit2:converter-moshi:$retrofit_version"
implementation "com.squareup.moshi:moshi:$moshi_version"
implementation "com.squareup.moshi:moshi-kotlin:$moshi_version"
このままだと、ビルド時にエラーが発生するので、「jetifier-processor」を追加する。
dependencies {
classpath 'com.android.tools.build:gradle:3.2.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
...
classpath 'com.android.tools.build.jetifier:jetifier-processor:1.0.0-beta02'
Dagger2 を実装
Application - Component - 各 Module
の構成作る必要があるので、まず、Application と Component を作成する。
- Component
import dagger.BindsInstance
import dagger.Component
import dagger.android.AndroidInjector
import dagger.android.support.AndroidSupportInjectionModule
import javax.inject.Singleton
@Singleton
@Component(modules = [AndroidSupportInjectionModule::class])
interface AppComponent : AndroidInjector<App> {
override fun inject(application: App)
@Component.Builder
interface Builder {
@BindsInstance
fun application(application: App): Builder
fun build(): AppComponent
}
}
- Application
import dagger.android.AndroidInjector
import dagger.android.support.DaggerApplication
class App : DaggerApplication() {
override fun applicationInjector(): AndroidInjector<out DaggerApplication> {
return DaggerAppComponent.builder().application(this).build()
}
}
- AndroidManifest
<uses-permission android:name="android.permission.INTERNET"/>
<application
android:name=".App"
Activity を実装
Activity の Module を作成する。
@Module
abstract class ActivityModule {
@ContributesAndroidInjector
abstract fun contributeMainActivity(): MainActivity
}
Component にモジュールを追加する。
@Component(modules = [AndroidSupportInjectionModule::class, ActivityModule::class])
interface AppComponent : AndroidInjector<App> {
...
AppCompatActivity を DaggerAppCompatActivity に変更する。
class MainActivity : DaggerAppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
...
Retrofit2 + Moshi を実装
例として、GitHub のユーザ情報を取得する。
data class User(
val name: String?,
val company: String?,
val email: String?,
val bio: String?,
val created_at: String?,
val updated_at: String?
)
Retrofit2 の interface を作成する。
interface GitHubService {
@GET("users/{username}")
fun getUser(@Path("username") user: String): Call<User>
}
Retrofit2 の Module を作成する。
@Module
class RetrofitModule {
@Provides
@Singleton
fun provideMoshi(): Moshi {
return Moshi.Builder().add(KotlinJsonAdapterFactory()).build()
}
@Provides
@Singleton
fun provideRetrofit(moshi: Moshi): Retrofit {
return Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(MoshiConverterFactory.create(moshi))
.build()
}
@Provides
@Singleton
fun provideRetrofitService(retrofit: Retrofit): GitHubService = retrofit.create(GitHubService::class.java)
}
Component にモジュールを追加する。
@Component(modules = [AndroidSupportInjectionModule::class, ActivityModule::class, RetrofitModule::class])
interface AppComponent : AndroidInjector<App> {
...
依存性の注入をする。
class MainActivity : DaggerAppCompatActivity() {
@Inject
lateinit var github: GitHubService
GitHub のユーザ情報を取得する。
override fun onResume() {
super.onResume()
val userCall: Call<User> = github.getUser("xxxxx")
userCall.enqueue(object : Callback<User> {
override fun onFailure(call: Call<User>, t: Throwable) {
}
override fun onResponse(call: Call<User>, response: Response<User>) {
if (response.isSuccessful) {
val user: User? = response.body()
}
}
})
}
ここまでで、Dagger2 + Retrofit2 + Moshi + Kotlin を使って通信するまでを記載しました。
本来は、シングルトンや依存関係など色々考慮して実装する必要がありますが、Dagger2 を使用することで、Module を追加し、Inject するだけで、シングルトンや依存関係などを考慮する必要がなくなります。