From 15cf1dff8237b93a8e79cc22226541624e4def06 Mon Sep 17 00:00:00 2001 From: cketti Date: Sat, 24 Mar 2018 05:30:32 +0100 Subject: [PATCH] Add KOIN for dependency injection --- gradle.properties | 1 + k9mail/build.gradle | 2 + k9mail/src/main/java/com/fsck/k9/DI.kt | 43 +++++++++++++++++++ k9mail/src/main/java/com/fsck/k9/K9.java | 1 + .../fsck/k9/ui/account/AccountsLiveData.kt | 13 +++--- .../com/fsck/k9/ui/settings/KoinModule.kt | 10 +++++ .../fsck/k9/ui/settings/SettingsActivity.kt | 5 ++- .../fsck/k9/ui/settings/SettingsViewModel.kt | 7 +-- .../com/fsck/k9/DependencyInjectionTest.kt | 15 +++++++ .../java/com/fsck/k9/K9RobolectricTest.kt | 14 ++++++ 10 files changed, 97 insertions(+), 14 deletions(-) create mode 100644 k9mail/src/main/java/com/fsck/k9/DI.kt create mode 100644 k9mail/src/main/java/com/fsck/k9/ui/settings/KoinModule.kt create mode 100644 k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt create mode 100644 k9mail/src/test/java/com/fsck/k9/K9RobolectricTest.kt diff --git a/gradle.properties b/gradle.properties index 33e500c22..ba4f99357 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,6 +3,7 @@ androidCompileSdkVersion=27 androidBuildToolsVersion=27.0.3 androidSupportLibraryVersion=27.0.2 timberVersion=4.5.1 +koinVersion=0.9.1 robolectricVersion=3.7.1 junitVersion=4.12 diff --git a/k9mail/build.gradle b/k9mail/build.gradle index 7ab16d73b..47514f424 100644 --- a/k9mail/build.gradle +++ b/k9mail/build.gradle @@ -42,6 +42,7 @@ dependencies { implementation 'com.xwray:groupie:2.0.3' implementation 'com.xwray:groupie-kotlin-android-extensions:2.0.3' implementation "org.jetbrains.anko:anko-coroutines:0.10.4" + implementation "org.koin:koin-android-architecture:${koinVersion}" androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' @@ -50,6 +51,7 @@ dependencies { testImplementation "com.google.truth:truth:${truthVersion}" testImplementation "org.mockito:mockito-core:${mockitoVersion}" testImplementation "org.jdom:jdom2:2.0.6" + testImplementation "org.koin:koin-test:${koinVersion}" } android { diff --git a/k9mail/src/main/java/com/fsck/k9/DI.kt b/k9mail/src/main/java/com/fsck/k9/DI.kt new file mode 100644 index 000000000..22088f3f9 --- /dev/null +++ b/k9mail/src/main/java/com/fsck/k9/DI.kt @@ -0,0 +1,43 @@ +package com.fsck.k9 + +import android.app.Application +import com.fsck.k9.ui.settings.settingsUiModule +import org.koin.Koin +import org.koin.KoinContext +import org.koin.android.ext.koin.with +import org.koin.android.logger.AndroidLogger +import org.koin.core.parameter.Parameters +import org.koin.dsl.module.applicationContext +import org.koin.log.EmptyLogger +import org.koin.standalone.StandAloneContext + +object DI { + private val mainModule = applicationContext { + bean { Preferences.getPreferences(get()) } + } + + val appModules = listOf( + mainModule, + settingsUiModule + ) + + @JvmStatic fun start(application: Application) { + @Suppress("ConstantConditionIf") + Koin.logger = if (BuildConfig.DEBUG) AndroidLogger() else EmptyLogger() + + StandAloneContext.startKoin(appModules) with application + } + + @JvmOverloads + @JvmStatic + fun get(clazz: Class, name: String = "", parameters: Parameters = { emptyMap() }): T { + val koinContext = StandAloneContext.koinContext as KoinContext + val kClass = clazz.kotlin + + return if (name.isEmpty()) { + koinContext.resolveInstance(kClass, parameters) { koinContext.beanRegistry.searchAll(kClass) } + } else { + koinContext.resolveInstance(kClass, parameters) { koinContext.beanRegistry.searchByName(name) } + } + } +} diff --git a/k9mail/src/main/java/com/fsck/k9/K9.java b/k9mail/src/main/java/com/fsck/k9/K9.java index f19251836..943d39f78 100644 --- a/k9mail/src/main/java/com/fsck/k9/K9.java +++ b/k9mail/src/main/java/com/fsck/k9/K9.java @@ -530,6 +530,7 @@ public class K9 extends Application { super.onCreate(); app = this; + DI.start(this); Globals.setContext(this); K9MailLib.setDebugStatus(new K9MailLib.DebugStatus() { diff --git a/k9mail/src/main/java/com/fsck/k9/ui/account/AccountsLiveData.kt b/k9mail/src/main/java/com/fsck/k9/ui/account/AccountsLiveData.kt index e2608ff3f..106b9aac3 100644 --- a/k9mail/src/main/java/com/fsck/k9/ui/account/AccountsLiveData.kt +++ b/k9mail/src/main/java/com/fsck/k9/ui/account/AccountsLiveData.kt @@ -1,29 +1,28 @@ package com.fsck.k9.ui.account import android.arch.lifecycle.LiveData -import android.content.Context import com.fsck.k9.Account import com.fsck.k9.Preferences import kotlinx.coroutines.experimental.android.UI import kotlinx.coroutines.experimental.launch import org.jetbrains.anko.coroutines.experimental.bg -class AccountsLiveData(context: Context) : LiveData>() { +class AccountsLiveData(val preferences: Preferences) : LiveData>() { init { - loadAccountsAsync(context) + loadAccountsAsync() } - private fun loadAccountsAsync(context: Context) { + private fun loadAccountsAsync() { launch(UI) { val accounts = bg { - loadAccounts(context) + loadAccounts() } value = accounts.await() } } - private fun loadAccounts(context: Context): List { - return Preferences.getPreferences(context).accounts + private fun loadAccounts(): List { + return preferences.accounts } } diff --git a/k9mail/src/main/java/com/fsck/k9/ui/settings/KoinModule.kt b/k9mail/src/main/java/com/fsck/k9/ui/settings/KoinModule.kt new file mode 100644 index 000000000..091264672 --- /dev/null +++ b/k9mail/src/main/java/com/fsck/k9/ui/settings/KoinModule.kt @@ -0,0 +1,10 @@ +package com.fsck.k9.ui.settings + +import com.fsck.k9.ui.account.AccountsLiveData +import org.koin.android.architecture.ext.viewModel +import org.koin.dsl.module.applicationContext + +val settingsUiModule = applicationContext { + bean { AccountsLiveData(get()) } + viewModel { SettingsViewModel(get()) } +} diff --git a/k9mail/src/main/java/com/fsck/k9/ui/settings/SettingsActivity.kt b/k9mail/src/main/java/com/fsck/k9/ui/settings/SettingsActivity.kt index dabb2105c..f59f0e9de 100644 --- a/k9mail/src/main/java/com/fsck/k9/ui/settings/SettingsActivity.kt +++ b/k9mail/src/main/java/com/fsck/k9/ui/settings/SettingsActivity.kt @@ -1,7 +1,6 @@ package com.fsck.k9.ui.settings import android.app.Activity -import android.arch.lifecycle.ViewModelProviders import android.content.Intent import android.os.Bundle import android.support.v7.widget.LinearLayoutManager @@ -16,8 +15,11 @@ import com.xwray.groupie.Item import com.xwray.groupie.Section import com.xwray.groupie.kotlinandroidextensions.ViewHolder import kotlinx.android.synthetic.main.activity_settings.* +import org.koin.android.architecture.ext.viewModel class SettingsActivity : K9Activity() { + private val viewModel: SettingsViewModel by viewModel() + private lateinit var settingsAdapter: GroupAdapter @@ -48,7 +50,6 @@ class SettingsActivity : K9Activity() { } private fun populateSettingsList() { - val viewModel = ViewModelProviders.of(this).get(SettingsViewModel::class.java) viewModel.accounts.observe(this) { accounts -> populateSettingsList(accounts) } diff --git a/k9mail/src/main/java/com/fsck/k9/ui/settings/SettingsViewModel.kt b/k9mail/src/main/java/com/fsck/k9/ui/settings/SettingsViewModel.kt index 227a1ca35..c05b435a9 100644 --- a/k9mail/src/main/java/com/fsck/k9/ui/settings/SettingsViewModel.kt +++ b/k9mail/src/main/java/com/fsck/k9/ui/settings/SettingsViewModel.kt @@ -1,9 +1,6 @@ package com.fsck.k9.ui.settings -import android.app.Application -import android.arch.lifecycle.AndroidViewModel +import android.arch.lifecycle.ViewModel import com.fsck.k9.ui.account.AccountsLiveData -internal class SettingsViewModel(application: Application) : AndroidViewModel(application) { - val accounts = AccountsLiveData(application) -} +internal class SettingsViewModel(val accounts: AccountsLiveData) : ViewModel() diff --git a/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt b/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt new file mode 100644 index 000000000..6c8c76b9e --- /dev/null +++ b/k9mail/src/test/java/com/fsck/k9/DependencyInjectionTest.kt @@ -0,0 +1,15 @@ +package com.fsck.k9 + +import org.junit.Test +import org.koin.Koin +import org.koin.log.PrintLogger +import org.koin.test.dryRun + +class DependencyInjectionTest : K9RobolectricTest() { + @Test + fun testDependencyTree() { + Koin.logger = PrintLogger() + + dryRun() + } +} diff --git a/k9mail/src/test/java/com/fsck/k9/K9RobolectricTest.kt b/k9mail/src/test/java/com/fsck/k9/K9RobolectricTest.kt new file mode 100644 index 000000000..2b6526450 --- /dev/null +++ b/k9mail/src/test/java/com/fsck/k9/K9RobolectricTest.kt @@ -0,0 +1,14 @@ +package com.fsck.k9 + +import android.app.Application +import org.junit.runner.RunWith +import org.koin.test.AutoCloseKoinTest +import org.robolectric.RobolectricTestRunner + +/** + * A Robolectric test that creates an instance of our [Application] class [K9]. + * + * See also [RobolectricTest]. + */ +@RunWith(RobolectricTestRunner::class) +abstract class K9RobolectricTest : AutoCloseKoinTest()