https://kotlinlang.org logo
#android
Title
# android
t

Thomas Nordmeyer

01/17/2020, 11:19 AM
Hi all, do you have any recommendation how to handle authentication loss in background (e.g. when receiving an 401 from a call in background). I am tending to invalidate the authentication in my repository, make my view models listen to the change and navigate to the login screen. But I am in doubt if I should observe repository members at all? Does anybody have a rough hint on how to do this with AAC?
w

wasyl

01/17/2020, 11:25 AM
if I should observe repository members at all
Is your doubt whether you should observe changes, or whether you should be accessing repository?
If the first one, then I’d say you should observe all members, that is your repository should only provide streams for the other layers to observe
t

Thomas Nordmeyer

01/17/2020, 12:28 PM
Details: I am storing my access token in AuthRepo.token. When it is null, user is logged out. Currently this is just a string var and whenever I want to know if user is logged in, I fetch the avalue (from VM) and propagate the info via LD observers. But it might happen that some other part of the app cancels the token while and my VM currently active does not know. I wonder how to notify it. My solution would be to keep the token as live data in Repository and let my VM listen to changes. This way my VM could react. But I read at some places I should not obsever Repository values.
But maybe there is some completely other solution pattern for my issue. Implementing a chek "Am I still logged in? Redirect to login screen if not" to every VM doesn't look like a good solution to me. Too much repetition.
... to every VM action ...
w

wasyl

01/17/2020, 12:41 PM
So for my perspective: entire state in my apps are always observable (currently RxJava observables). User being logged in (typically a state session observable) is one example, but I have streams for things presented to the user, and whenever they change in the repository, view must update too
👍 1
✔️ 1
I highly recommend this pattern, as it makes it so that state in your app is always consistent: you’ll never forget to query the
var
or miss some case, because the only way to get anything is to subscribe to a stream
b

bhatnagarm

01/17/2020, 1:27 PM
Well I would recommend having a base repository class exposing some common data like token, as a live data
And then have each repository being extended from base. Now in you each VM can just observe to the changes and act appropriately. Should be good enough for such cases.
t

Thomas Nordmeyer

01/17/2020, 3:53 PM
Thanks Lukasz, Maynank, thats what I thought of. You think this won't break recommended architecture?
w

wasyl

01/17/2020, 9:46 PM
It depends on what you consider recommended architecture. In my experience a CQRS-like approach works extremely well, specifically observing all the application state. But it’s difficult to say what will work or not work for you. To me observing state is definitely a good practice
t

Thomas Nordmeyer

01/21/2020, 8:16 AM
OK, thanks a lot.
We now just observe changes in repositories from ViewModel. Was a bit astonished that Kotlin does not provide a simple Observable (the Java one is typeless) and thus created my own
Copy code
class Observable<T> {
    private val listeners = mutableListOf<(T?) -> Unit>()

    /**
     * Holds value and notifies listeners when value is modified
     */
    var value: T? = null
        set(value) {
            val touched = field != value
            field = value
            if (touched) callObservers()
        }

    /**
     * registers observer
     */
    fun observe(listener: (T?) -> Unit) = listeners.add(listener)
    /**
     * unregisters observer
     */
    fun removeObserver(listener: (T?) -> Unit) = listeners.remove(listener)
    /**
     * calls all observers with current value
     */
    fun callObservers() = listeners.forEach { it(value) }
}