Implemented CurrentActivityTracker to keep track of current activity and to get rid of MainActivity dependency for RouterAndroid

This commit is contained in:
dankito 2020-05-04 17:18:27 +02:00
parent bf6d7b9896
commit e954119670
6 changed files with 156 additions and 28 deletions

View File

@ -4,13 +4,13 @@ import android.os.Bundle
import android.view.Menu import android.view.Menu
import android.view.MotionEvent import android.view.MotionEvent
import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar import androidx.appcompat.widget.Toolbar
import androidx.drawerlayout.widget.DrawerLayout import androidx.drawerlayout.widget.DrawerLayout
import com.github.clans.fab.FloatingActionMenu import com.github.clans.fab.FloatingActionMenu
import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main.*
import net.dankito.banking.fints4java.android.di.BankingComponent import net.dankito.banking.fints4java.android.di.BankingComponent
import net.dankito.banking.fints4java.android.di.BankingModule import net.dankito.banking.fints4java.android.di.BankingModule
import net.dankito.banking.fints4java.android.ui.activities.BaseActivity
import net.dankito.banking.fints4java.android.ui.views.DrawerView import net.dankito.banking.fints4java.android.ui.views.DrawerView
import net.dankito.banking.fints4java.android.ui.views.MainActivityFloatingActionMenuButton import net.dankito.banking.fints4java.android.ui.views.MainActivityFloatingActionMenuButton
import net.dankito.banking.ui.presenter.BankingPresenter import net.dankito.banking.ui.presenter.BankingPresenter
@ -18,7 +18,7 @@ import org.slf4j.LoggerFactory
import javax.inject.Inject import javax.inject.Inject
class MainActivity : AppCompatActivity() { class MainActivity : BaseActivity() {
companion object { companion object {
private val log = LoggerFactory.getLogger(MainActivity::class.java) private val log = LoggerFactory.getLogger(MainActivity::class.java)

View File

@ -1,10 +1,10 @@
package net.dankito.banking.fints4java.android package net.dankito.banking.fints4java.android
import androidx.appcompat.app.AppCompatActivity
import net.dankito.banking.fints4java.android.ui.dialogs.AddAccountDialog import net.dankito.banking.fints4java.android.ui.dialogs.AddAccountDialog
import net.dankito.banking.fints4java.android.ui.dialogs.EnterAtcDialog import net.dankito.banking.fints4java.android.ui.dialogs.EnterAtcDialog
import net.dankito.banking.fints4java.android.ui.dialogs.EnterTanDialog 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.dialogs.TransferMoneyDialog
import net.dankito.banking.fints4java.android.ui.util.CurrentActivityTracker
import net.dankito.banking.ui.IRouter import net.dankito.banking.ui.IRouter
import net.dankito.banking.ui.model.Account import net.dankito.banking.ui.model.Account
import net.dankito.banking.ui.model.BankAccount import net.dankito.banking.ui.model.BankAccount
@ -18,46 +18,56 @@ import java.util.concurrent.CountDownLatch
import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.atomic.AtomicReference
open class RouterAndroid(protected val activity: AppCompatActivity) : IRouter { open class RouterAndroid(protected val activityTracker: CurrentActivityTracker) : IRouter {
override fun showAddAccountDialog(presenter: BankingPresenter) { override fun showAddAccountDialog(presenter: BankingPresenter) {
AddAccountDialog().show(activity) activityTracker.currentActivity?.let { activity ->
AddAccountDialog().show(activity)
}
} }
override fun getTanFromUserFromNonUiThread(account: Account, tanChallenge: TanChallenge, presenter: BankingPresenter): EnterTanResult { override fun getTanFromUserFromNonUiThread(account: Account, tanChallenge: TanChallenge, presenter: BankingPresenter): EnterTanResult {
val enteredTan = AtomicReference<EnterTanResult>(null) return activityTracker.currentActivity?.let { activity ->
val tanEnteredLatch = CountDownLatch(1) val enteredTan = AtomicReference<EnterTanResult>(null)
val tanEnteredLatch = CountDownLatch(1)
activity.runOnUiThread { activity.runOnUiThread {
EnterTanDialog().show(account, tanChallenge, activity, false) { EnterTanDialog().show(account, tanChallenge, activity, false) {
enteredTan.set(it) enteredTan.set(it)
tanEnteredLatch.countDown() tanEnteredLatch.countDown()
}
} }
try { tanEnteredLatch.await() } catch (ignored: Exception) { }
enteredTan.get()
} }
?: EnterTanResult.userDidNotEnterTan()
try { tanEnteredLatch.await() } catch (ignored: Exception) { }
return enteredTan.get()
} }
override fun getAtcFromUserFromNonUiThread(tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult { override fun getAtcFromUserFromNonUiThread(tanMedium: TanGeneratorTanMedium): EnterTanGeneratorAtcResult {
val result = AtomicReference<EnterTanGeneratorAtcResult>(null) return activityTracker.currentActivity?.let { activity ->
val tanEnteredLatch = CountDownLatch(1) val result = AtomicReference<EnterTanGeneratorAtcResult>(null)
val tanEnteredLatch = CountDownLatch(1)
activity.runOnUiThread { activity.runOnUiThread {
EnterAtcDialog().show(tanMedium, activity, false) { enteredResult -> EnterAtcDialog().show(tanMedium, activity, false) { enteredResult ->
result.set(enteredResult) result.set(enteredResult)
tanEnteredLatch.countDown() tanEnteredLatch.countDown()
}
} }
try { tanEnteredLatch.await() } catch (ignored: Exception) { }
result.get()
} }
?: EnterTanGeneratorAtcResult.userDidNotEnterTan()
try { tanEnteredLatch.await() } catch (ignored: Exception) { }
return result.get()
} }
override fun showTransferMoneyDialog(presenter: BankingPresenter, preselectedBankAccount: BankAccount?, preselectedValues: TransferMoneyData?) { override fun showTransferMoneyDialog(presenter: BankingPresenter, preselectedBankAccount: BankAccount?, preselectedValues: TransferMoneyData?) {
TransferMoneyDialog().show(activity, preselectedBankAccount, preselectedValues) activityTracker.currentActivity?.let { activity ->
TransferMoneyDialog().show(activity, preselectedBankAccount, preselectedValues)
}
} }
} }

View File

@ -2,6 +2,7 @@ package net.dankito.banking.fints4java.android.di
import dagger.Component import dagger.Component
import net.dankito.banking.fints4java.android.MainActivity import net.dankito.banking.fints4java.android.MainActivity
import net.dankito.banking.fints4java.android.ui.activities.BaseActivity
import net.dankito.banking.fints4java.android.ui.dialogs.AddAccountDialog 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.EnterTanDialog
import net.dankito.banking.fints4java.android.ui.dialogs.TransferMoneyDialog import net.dankito.banking.fints4java.android.ui.dialogs.TransferMoneyDialog
@ -18,6 +19,8 @@ interface BankingComponent {
} }
fun inject(baseActivity: BaseActivity)
fun inject(mainActivity: MainActivity) fun inject(mainActivity: MainActivity)
fun inject(homeFragment: HomeFragment) fun inject(homeFragment: HomeFragment)

View File

@ -5,6 +5,7 @@ import androidx.appcompat.app.AppCompatActivity
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import net.dankito.banking.fints4java.android.RouterAndroid import net.dankito.banking.fints4java.android.RouterAndroid
import net.dankito.banking.fints4java.android.ui.util.CurrentActivityTracker
import net.dankito.banking.fints4java.android.util.Base64ServiceAndroid import net.dankito.banking.fints4java.android.util.Base64ServiceAndroid
import net.dankito.banking.fints4javaBankingClientCreator import net.dankito.banking.fints4javaBankingClientCreator
import net.dankito.banking.persistence.IBankingPersistence import net.dankito.banking.persistence.IBankingPersistence
@ -114,8 +115,14 @@ class BankingModule(private val applicationContext: Context) {
@Provides @Provides
@Singleton @Singleton
fun provideRouter() : IRouter { fun provideCurrentActivityTracker() : CurrentActivityTracker {
return RouterAndroid(mainActivity) return CurrentActivityTracker()
}
@Provides
@Singleton
fun provideRouter(currentActivityTracker: CurrentActivityTracker) : IRouter {
return RouterAndroid(currentActivityTracker)
} }

View File

@ -0,0 +1,67 @@
package net.dankito.banking.fints4java.android.ui.activities
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import net.dankito.banking.fints4java.android.di.BankingComponent
import net.dankito.banking.fints4java.android.ui.util.CurrentActivityTracker
import org.slf4j.LoggerFactory
import javax.inject.Inject
abstract class BaseActivity : AppCompatActivity() {
companion object {
private val log = LoggerFactory.getLogger(BaseActivity::class.java)
}
@Inject
protected lateinit var currentActivityTracker: CurrentActivityTracker
init {
BankingComponent.component.inject(this)
}
override fun onCreate(savedInstanceState: Bundle?) {
log.info("Creating Activity $this")
super.onCreate(savedInstanceState)
}
override fun onStart() {
super.onStart()
currentActivityTracker.currentActivity = this
log.info("Started Activity $this")
}
override fun onResume() {
super.onResume()
currentActivityTracker.currentActivity = this
log.info("Resumed Activity $this")
}
override fun onPause() {
log.info("Paused Activity $this")
super.onPause()
}
override fun onStop() {
log.info("Stopped Activity $this")
super.onStop()
}
override fun onDestroy() {
log.info("Destroyed Activity $this")
super.onDestroy()
}
}

View File

@ -0,0 +1,41 @@
package net.dankito.banking.fints4java.android.ui.util
import net.dankito.banking.fints4java.android.ui.activities.BaseActivity
import java.util.*
import java.util.concurrent.CopyOnWriteArrayList
import kotlin.concurrent.schedule
open class CurrentActivityTracker {
var currentActivity: BaseActivity? = null
set(value) {
field = value // TODO: check field != value
if (value != null) {
callAndClearNextActivitySetListeners(value)
}
}
protected val nextActivitySetListeners = CopyOnWriteArrayList<(BaseActivity) -> Unit>()
open fun addNextActivitySetListener(listener: (BaseActivity) -> Unit) {
synchronized(nextActivitySetListeners) {
nextActivitySetListeners.add(listener)
}
}
protected open fun callAndClearNextActivitySetListeners(activity: BaseActivity) {
synchronized(nextActivitySetListeners) {
val listenersCopy = ArrayList(nextActivitySetListeners)
nextActivitySetListeners.clear()
Timer().schedule(500) { // wait some time till activity is initialized
listenersCopy.forEach { it(activity) }
}
}
}
}