Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Clean architecture login flow

I am developing a login screen in my Android application with a clean architecture.

When using the login in successfully, I need to save the token to shared preferences.

And on the splash screen, I need to check whether a user is logged in or not

So my question is that where is the perfect place:

  1. To save token

should I save token in LoginUseCase (domain layer)

class LoginUseCase(private val userRepository: UserRepository, private val schedulerProvider: SchedulerProvider) {

    fun execute(username: String, password: String): Single<Token> {
        return userRepository.login(username, password)
            .andThen(userRepository.saveToken(.....)
            .subscribeOn(schedulerProvider.getIOScheduler())
            .observeOn(schedulerProvider.getUIScheduler())
    }

}

Or should I make save token as an UseCase and save the token in presenter layer

class LoginPresenter(private val view: LoginContract.View,
                     private val setLoginStateUseCase: SetLoginStateUseCase,
                     private val loginUseCase: LoginUseCase,
                     private val schedulerProvider: SchedulerProvider): LoginContract.Presenter {

    private val compositeDisposable = CompositeDisposable()

    override fun performLogin(username: String, password: String) {

        if (username.isNullOrEmpty() || password.isNullOrEmpty()) {
            view.onShowLoginError("Field should not be empty")
        } else {
            view.showLoading()
            val disposable = loginUseCase.execute(username, password)
                    .subscribeOn(schedulerProvider.getIOScheduler())
                    .observeOn(schedulerProvider.getUIScheduler())
                    .andThen(setLoginStateUseCase.execute())
                    .subscribe({
                        view.hideLoading()
                        view.onLoginSuccess()
                    }, {error ->
                        view.hideLoading()
                        view.onShowLoginError(error.localizedMessage)
                    })
            compositeDisposable.add(disposable)
        }
    }

The same question with check user is logged in or not. Should I make that action a use-case?

like image 561
coinhndp Avatar asked Nov 04 '18 17:11

coinhndp


Video Answer


1 Answers

In my opinion it makes pretty much sense to perform that operation in the domain layer use case. Imagine you have another different module in the same project for a TV app. It's likely that the LoginPresenter may differ from the mobile app module's one, however, you could be able to reuse the very same use case. Thus, you don't have to be aware on each LoginPresenter variation you implement to save the token once the use case is executed.

On the other hand, I'd suggest to take a look at how the folks of Google face the login process using a delegate pattern in their Google I/O application. It's a very common pattern to use a currentUser observable along your application giving you plenty of advantages. For example, although I wouldn't label it as a pure clean architecture reference project, the guys of kickstarter developed an interesting MVVM+RxJava architecture using the currentUser paradigm I've talked about which deserves to have a glance also.

like image 146
GoRoS Avatar answered Oct 26 '22 22:10

GoRoS