https://kotlinlang.org logo
#android-architecture
Title
# android-architecture
d

Davide Giuseppe Farella

02/05/2019, 8:57 PM
Assuming that we have a single Activity app with an architecture that delivers all the exceptions to the presentation layer. Actually I got an interface
AndroidComponent
that will be implemented by `Activity`es, `Fragment`s, `Worker`s/`Service`s ( and basically nothing else ) that provides a reference to
Notifier
.
Notifier
jobs are 1 inform
Timber
( that will eventually inform
Crashlytics
) and 2 show a message to the user. Actually the message to the user is delivered through an abstraction of
Toast
injected in the constructor; but I would like to use a
SnackBar
instead, if the app is in foreground: so I was thinking about a
SnackBarManager
( fantasy name 😁 ) that will be implemented by the
Activity
which will pass the set/remove the interface to
Notifier
(
onStart()' /' onStop()
) , so the Notifier could call
snackBarManager?.let { it.showSomething() } ?: showToast()
What do you think about that? 🙂
d

dave08

02/07/2019, 3:50 AM
Why should the P layer know about display specifics (snackbar, notif...)? AFAIK the P layer should just say displayMessageXXX() and the view decides how. That way if Android deprecates snakbar into something else, you only touch the V layer... its more verbose, but also testing is more explicit when you test for use of the exact message in your view mock. Another way (less explicit and heavier on the view side) might be a sealed class in show/clearMessage(type).
d

Davide Giuseppe Farella

02/08/2019, 1:09 PM
@dave08 sorry for the late answer, didn't got any notification. In first place, no one but Activity knows about
Snackbar
, P just know
abstract fun showSnackbar()
. Also I can't implement all the logic in the View, since "everybody" can handle an error and also may the View won't be available ( eg. Background service ). Actually I got something like
Copy code
interface AndroidComponent: KoinComponent {
    val notifier get() = get<AndroidNotifier>() 
} 

interface SnackbarManager {
    fun showSnackbar( args ) 
} 

interface Notifier {
    info/warn/etc methods
} 

class AndroidNotifier( private val toast: Toast /* abstraction of Android Toast */ ) {
    val snackbarManager: SnackbarManager? = null
    overrides -> show( args ) 
    private fun show( args ) {
        snackbarManager?.let { it.showSnackbar( args ) 
            ?: toast.show( args ) 
    } 
} 

class MyActivity: AppCompatActivity(), AndroidComponent, SnackbarManager {
    override showSnackbar( args ) { ... } 
    override fun onStart() {
        notifier.snackbarManager = this
    } 
    override fun onStop() {
        notifier.snackbarManager = null
    } 
}
d

dave08

02/09/2019, 5:17 PM
I meant the name
showSnackbar
is an implementation detail that P doesn't need to know... the implementation can be seperate, just that only the V layer should depend on and know about it. Instead of showSnackbar, I'd have showError(someSealedClassForErrors), or showMessage(someSealedClassForErrors), and delegate that to the snackbar manager for actual displaying. That way, you can switch out the snackbar for whatever without changing your presentation layer, just as long as you display what the contract implies. See SOLID principles, there should be only one reason for a class to change. @Davide Giuseppe Farella
d

Davide Giuseppe Farella

02/09/2019, 5:22 PM
I see, that makes sense 🙂 thanks for the hint! Is the rest of the implementation ok?
6 Views