From d6b136e7f34620c016bf73399186e86ab2b57a6f Mon Sep 17 00:00:00 2001 From: dankito Date: Thu, 23 Apr 2020 20:35:25 +0200 Subject: [PATCH] Using now Dagger to inject dependencies (fixes that on resume Dialogs don't crash) --- build.gradle | 2 + fints4javaAndroidApp/build.gradle | 6 + .../fints4java/android/MainActivity.kt | 25 +++-- .../fints4java/android/RouterAndroid.kt | 6 +- .../fints4java/android/di/BankingComponent.kt | 31 ++++++ .../fints4java/android/di/BankingModule.kt | 103 ++++++++++++++++++ .../android/ui/dialogs/AddAccountDialog.kt | 15 ++- .../android/ui/dialogs/EnterTanDialog.kt | 16 ++- .../android/ui/dialogs/TransferMoneyDialog.kt | 20 +++- .../android/ui/home/HomeFragment.kt | 21 ++-- 10 files changed, 207 insertions(+), 38 deletions(-) create mode 100644 fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingComponent.kt create mode 100644 fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingModule.kt diff --git a/build.gradle b/build.gradle index 2b03dd4f..89977cfa 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,8 @@ ext { materialComponentsVersion = "1.1.0" + daggerVersion = "2.27" + /* JavaFX */ diff --git a/fints4javaAndroidApp/build.gradle b/fints4javaAndroidApp/build.gradle index b9ec94e3..a9e33265 100644 --- a/fints4javaAndroidApp/build.gradle +++ b/fints4javaAndroidApp/build.gradle @@ -1,6 +1,8 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-kapt' + android { compileSdkVersion 28 @@ -89,6 +91,10 @@ dependencies { implementation "com.mikepenz:fontawesome-typeface:5.9.0.0-kotlin@aar" + kapt "com.google.dagger:dagger-compiler:$daggerVersion" + implementation "com.google.dagger:dagger:$daggerVersion" + + implementation 'androidx.navigation:navigation-fragment:2.0.0-rc02' implementation 'androidx.navigation:navigation-ui:2.0.0-rc02' implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0' diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/MainActivity.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/MainActivity.kt index 6fec6ad8..ad722449 100644 --- a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/MainActivity.kt +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/MainActivity.kt @@ -9,15 +9,14 @@ import androidx.appcompat.widget.Toolbar import androidx.drawerlayout.widget.DrawerLayout import com.github.clans.fab.FloatingActionMenu import kotlinx.android.synthetic.main.activity_main.* +import net.dankito.banking.fints4java.android.di.BankingComponent +import net.dankito.banking.fints4java.android.di.BankingModule +import net.dankito.banking.fints4java.android.di.DaggerBankingComponent import net.dankito.banking.fints4java.android.ui.views.DrawerView import net.dankito.banking.fints4java.android.ui.views.MainActivityFloatingActionMenuButton -import net.dankito.banking.fints4java.android.util.Base64ServiceAndroid -import net.dankito.banking.fints4javaBankingClientCreator -import net.dankito.banking.persistence.BankingPersistenceJson import net.dankito.banking.ui.presenter.BankingPresenter -import net.dankito.utils.web.client.OkHttpWebClient import org.slf4j.LoggerFactory -import java.io.File +import javax.inject.Inject class MainActivity : AppCompatActivity() { @@ -36,20 +35,28 @@ class MainActivity : AppCompatActivity() { private lateinit var floatingActionMenuButton: MainActivityFloatingActionMenuButton - lateinit var presenter: BankingPresenter + @Inject + protected lateinit var presenter: BankingPresenter override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - val dataFolder = File(this.filesDir, "data/accounts") + setupDependencyInjection() - presenter = BankingPresenter(fints4javaBankingClientCreator(OkHttpWebClient(), Base64ServiceAndroid()), dataFolder, - BankingPersistenceJson(File(dataFolder, "accounts.json")), RouterAndroid(this)) + BankingComponent.component.inject(this) initUi() } + private fun setupDependencyInjection() { + val component = DaggerBankingComponent.builder() + .bankingModule(BankingModule(this)) + .build() + + BankingComponent.component = component + } + private fun initUi() { setContentView(R.layout.activity_main) diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/RouterAndroid.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/RouterAndroid.kt index 08198985..389fc653 100644 --- a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/RouterAndroid.kt +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/RouterAndroid.kt @@ -21,7 +21,7 @@ import java.util.concurrent.atomic.AtomicReference open class RouterAndroid(protected val activity: AppCompatActivity) : IRouter { override fun showAddAccountDialog(presenter: BankingPresenter) { - AddAccountDialog().show(activity, presenter) + AddAccountDialog().show(activity) } override fun getTanFromUserFromNonUiThread(account: Account, tanChallenge: TanChallenge, presenter: BankingPresenter): EnterTanResult { @@ -29,7 +29,7 @@ open class RouterAndroid(protected val activity: AppCompatActivity) : IRouter { val tanEnteredLatch = CountDownLatch(1) activity.runOnUiThread { - EnterTanDialog().show(account, tanChallenge, presenter, activity, false) { + EnterTanDialog().show(account, tanChallenge, activity, false) { enteredTan.set(it) tanEnteredLatch.countDown() } @@ -57,7 +57,7 @@ open class RouterAndroid(protected val activity: AppCompatActivity) : IRouter { } override fun showTransferMoneyDialog(presenter: BankingPresenter, preselectedBankAccount: BankAccount?, preselectedValues: TransferMoneyData?) { - TransferMoneyDialog().show(activity, presenter, preselectedBankAccount, preselectedValues) + TransferMoneyDialog().show(activity, preselectedBankAccount, preselectedValues) } } \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingComponent.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingComponent.kt new file mode 100644 index 00000000..0c2545b3 --- /dev/null +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingComponent.kt @@ -0,0 +1,31 @@ +package net.dankito.banking.fints4java.android.di + +import dagger.Component +import net.dankito.banking.fints4java.android.MainActivity +import net.dankito.banking.fints4java.android.ui.dialogs.AddAccountDialog +import net.dankito.banking.fints4java.android.ui.dialogs.EnterTanDialog +import net.dankito.banking.fints4java.android.ui.dialogs.TransferMoneyDialog +import net.dankito.banking.fints4java.android.ui.home.HomeFragment +import javax.inject.Singleton + + +@Singleton +@Component(modules = arrayOf(BankingModule::class)) +interface BankingComponent { + + companion object { + lateinit var component: BankingComponent + } + + + fun inject(mainActivity: MainActivity) + + fun inject(homeFragment: HomeFragment) + + fun inject(addAccountDialog: AddAccountDialog) + + fun inject(enterTanDialog: EnterTanDialog) + + fun inject(transferMoneyDialog: TransferMoneyDialog) + +} \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingModule.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingModule.kt new file mode 100644 index 00000000..aa87510f --- /dev/null +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/di/BankingModule.kt @@ -0,0 +1,103 @@ +package net.dankito.banking.fints4java.android.di + +import android.content.Context +import androidx.appcompat.app.AppCompatActivity +import dagger.Module +import dagger.Provides +import net.dankito.banking.fints4java.android.RouterAndroid +import net.dankito.banking.fints4java.android.util.Base64ServiceAndroid +import net.dankito.banking.fints4javaBankingClientCreator +import net.dankito.banking.persistence.BankingPersistenceJson +import net.dankito.banking.persistence.IBankingPersistence +import net.dankito.banking.ui.IBankingClientCreator +import net.dankito.banking.ui.IRouter +import net.dankito.banking.ui.presenter.BankingPresenter +import net.dankito.utils.IThreadPool +import net.dankito.utils.ThreadPool +import net.dankito.utils.serialization.ISerializer +import net.dankito.utils.serialization.JacksonJsonSerializer +import net.dankito.utils.web.client.IWebClient +import net.dankito.utils.web.client.OkHttpWebClient +import java.io.File +import javax.inject.Named +import javax.inject.Singleton + + +@Module +class BankingModule(internal val mainActivity: AppCompatActivity) { + + companion object { + + const val DataFolderKey = "data.folder" + + } + + + private val applicationContext = mainActivity.applicationContext + + + @Provides + @Singleton + fun provideApplicationContext() : Context { + return applicationContext + } + + @Provides + @Singleton + @Named(DataFolderKey) + fun provideDataFolder(applicationContext: Context) : File { + return File(applicationContext.filesDir, "data/accounts") + } + + + @Provides + @Singleton + fun provideBankingPresenter(bankingClientCreator: IBankingClientCreator, @Named(DataFolderKey) dataFolder: File, + persister: IBankingPersistence, router: IRouter, threadPool: IThreadPool) : BankingPresenter { + return BankingPresenter(bankingClientCreator, dataFolder, persister, router, threadPool) + } + + @Provides + @Singleton + fun provideBankingClientCreator(webClient: IWebClient, base64Service: net.dankito.banking.util.IBase64Service) : IBankingClientCreator { + return fints4javaBankingClientCreator(webClient, base64Service) + } + + @Provides + @Singleton + fun provideBankingPersistence(@Named(DataFolderKey) dataFolder: File, serializer: ISerializer) : IBankingPersistence { + return BankingPersistenceJson(File(dataFolder, "accounts.json"), serializer) + } + + @Provides + @Singleton + fun provideRouter() : IRouter { + return RouterAndroid(mainActivity) + } + + + @Provides + @Singleton + fun provideWebClient() : IWebClient { + return OkHttpWebClient() + } + + @Provides + @Singleton + fun provideSerializer() : ISerializer { + return JacksonJsonSerializer() + } + + @Provides + @Singleton + fun provideBase64Service() : net.dankito.banking.util.IBase64Service { + return Base64ServiceAndroid() + } + + @Provides + @Singleton + fun provideThreadPool() : IThreadPool { + return ThreadPool() + } + +} \ No newline at end of file diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/AddAccountDialog.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/AddAccountDialog.kt index c1ed8295..2821dd11 100644 --- a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/AddAccountDialog.kt +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/AddAccountDialog.kt @@ -19,11 +19,13 @@ import com.otaliastudios.autocomplete.AutocompleteCallback import kotlinx.android.synthetic.main.dialog_add_account.* import kotlinx.android.synthetic.main.dialog_add_account.view.* import net.dankito.banking.fints4java.android.R +import net.dankito.banking.fints4java.android.di.BankingComponent import net.dankito.banking.fints4java.android.ui.adapter.presenter.BankInfoPresenter import net.dankito.banking.ui.model.responses.AddAccountResponse import net.dankito.banking.ui.presenter.BankingPresenter import net.dankito.fints.model.BankInfo import net.dankito.utils.android.extensions.asActivity +import javax.inject.Inject open class AddAccountDialog : DialogFragment() { @@ -33,16 +35,21 @@ open class AddAccountDialog : DialogFragment() { } - protected lateinit var presenter: BankingPresenter - protected var selectedBank: BankInfo? = null - fun show(activity: AppCompatActivity, presenter: BankingPresenter, fullscreen: Boolean = false) { - this.presenter = presenter + @Inject + protected lateinit var presenter: BankingPresenter + + + init { + BankingComponent.component.inject(this) presenter.preloadBanksAsync() + } + + fun show(activity: AppCompatActivity, fullscreen: Boolean = false) { val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.FloatingDialog setStyle(STYLE_NORMAL, style) diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/EnterTanDialog.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/EnterTanDialog.kt index 1b557e28..864a32d2 100644 --- a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/EnterTanDialog.kt +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/EnterTanDialog.kt @@ -15,6 +15,7 @@ import androidx.fragment.app.DialogFragment import kotlinx.android.synthetic.main.dialog_enter_tan.view.* import kotlinx.android.synthetic.main.view_tan_image.view.* import net.dankito.banking.fints4java.android.R +import net.dankito.banking.fints4java.android.di.BankingComponent import net.dankito.banking.fints4java.android.ui.adapter.TanMediumAdapter import net.dankito.banking.fints4java.android.ui.adapter.TanProceduresAdapter import net.dankito.banking.fints4java.android.ui.listener.ListItemSelectedListener @@ -22,6 +23,7 @@ import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.responses.BankingClientResponse import net.dankito.banking.ui.model.tan.* import net.dankito.banking.ui.presenter.BankingPresenter +import javax.inject.Inject open class EnterTanDialog : DialogFragment() { @@ -37,19 +39,25 @@ open class EnterTanDialog : DialogFragment() { protected lateinit var tanChallenge: TanChallenge - protected lateinit var presenter: BankingPresenter - protected lateinit var tanEnteredCallback: (EnterTanResult) -> Unit protected val tanMediumAdapter = TanMediumAdapter() - open fun show(account: Account, tanChallenge: TanChallenge, presenter: BankingPresenter, activity: AppCompatActivity, + @Inject + protected lateinit var presenter: BankingPresenter + + + init { + BankingComponent.component.inject(this) + } + + + open fun show(account: Account, tanChallenge: TanChallenge, activity: AppCompatActivity, fullscreen: Boolean = false, tanEnteredCallback: (EnterTanResult) -> Unit) { this.account = account this.tanChallenge = tanChallenge - this.presenter = presenter this.tanEnteredCallback = tanEnteredCallback val style = if(fullscreen) R.style.FullscreenDialogWithStatusBar else R.style.FloatingDialog diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/TransferMoneyDialog.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/TransferMoneyDialog.kt index 14894a8c..b6984ee9 100644 --- a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/TransferMoneyDialog.kt +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/dialogs/TransferMoneyDialog.kt @@ -12,6 +12,7 @@ import androidx.fragment.app.DialogFragment import kotlinx.android.synthetic.main.dialog_transfer_money.* import kotlinx.android.synthetic.main.dialog_transfer_money.view.* import net.dankito.banking.fints4java.android.R +import net.dankito.banking.fints4java.android.di.BankingComponent import net.dankito.banking.fints4java.android.ui.adapter.BankAccountsAdapter import net.dankito.banking.fints4java.android.ui.listener.ListItemSelectedListener import net.dankito.banking.fints4java.android.util.StandardTextWatcher @@ -24,6 +25,7 @@ import net.dankito.fints.model.BankInfo import net.dankito.utils.android.extensions.asActivity import java.math.BigDecimal import java.text.DecimalFormatSymbols +import javax.inject.Inject open class TransferMoneyDialog : DialogFragment() { @@ -33,8 +35,6 @@ open class TransferMoneyDialog : DialogFragment() { } - protected lateinit var presenter: BankingPresenter - protected var preselectedBankAccount: BankAccount? = null protected lateinit var bankAccount: BankAccount @@ -47,12 +47,20 @@ open class TransferMoneyDialog : DialogFragment() { protected var foundBankForEnteredIban = false - open fun show(activity: AppCompatActivity, presenter: BankingPresenter, preselectedBankAccount: BankAccount?, fullscreen: Boolean = false) { - show(activity, presenter, preselectedBankAccount, null, fullscreen) + @Inject + protected lateinit var presenter: BankingPresenter + + + init { + BankingComponent.component.inject(this) } - open fun show(activity: AppCompatActivity, presenter: BankingPresenter, preselectedBankAccount: BankAccount?, preselectedValues: TransferMoneyData?, fullscreen: Boolean = false) { - this.presenter = presenter + + open fun show(activity: AppCompatActivity, preselectedBankAccount: BankAccount?, fullscreen: Boolean = false) { + show(activity, preselectedBankAccount, null, fullscreen) + } + + open fun show(activity: AppCompatActivity, preselectedBankAccount: BankAccount?, preselectedValues: TransferMoneyData?, fullscreen: Boolean = false) { this.preselectedBankAccount = preselectedBankAccount this.preselectedValues = preselectedValues diff --git a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeFragment.kt b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeFragment.kt index 133085df..b5b7a686 100644 --- a/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeFragment.kt +++ b/fints4javaAndroidApp/src/main/java/net/dankito/banking/fints4java/android/ui/home/HomeFragment.kt @@ -12,14 +12,15 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProviders import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView -import net.dankito.banking.fints4java.android.MainActivity import net.dankito.banking.fints4java.android.R +import net.dankito.banking.fints4java.android.di.BankingComponent import net.dankito.banking.fints4java.android.ui.adapter.AccountTransactionAdapter import net.dankito.banking.ui.model.AccountTransaction import net.dankito.banking.ui.model.parameters.TransferMoneyData import net.dankito.banking.ui.model.responses.GetTransactionsResponse import net.dankito.banking.ui.presenter.BankingPresenter import net.dankito.utils.android.extensions.asActivity +import javax.inject.Inject class HomeFragment : Fragment() { @@ -38,7 +39,13 @@ class HomeFragment : Fragment() { protected var appliedTransactionsFilter = "" - private lateinit var presenter: BankingPresenter + @Inject + protected lateinit var presenter: BankingPresenter + + + init { + BankingComponent.component.inject(this) + } override fun onCreate(savedInstanceState: Bundle?) { @@ -62,8 +69,6 @@ class HomeFragment : Fragment() { registerForContextMenu(rcyvwAccountTransactions) // this is actually bad, splits code as context menu is created in AccountTransactionAdapter - initLogic() - return root } @@ -122,14 +127,6 @@ class HomeFragment : Fragment() { } - private fun initLogic() { - - // TODO: this is such a bad code style - (context as? MainActivity)?.presenter?.let { presenter -> - this.presenter = presenter - } - } - private fun initLogicAfterUiInitialized() { presenter.addSelectedBankAccountsChangedListener { handleSelectedBankAccountsChanged() }