Реализация регистрации пользователей в Android-приложении согласно MVVM

Рейтинг: 0Ответов: 1Опубликовано: 13.05.2023

Пишу Android-приложение с возможностью регистрации пользователя (в качестве backend'а использую Google Firebase). Пытаюсь писать приложение в соответствие с паттерном MVVM. Код, вызывающий сомнения представлен ниже.

View

private fun registrationUser(email: String, password: String) {
    // Проверяю соединение с интернетом, в случае неудачи показываю предупреждение
    if (viewModel.inNetworkAvailable()) {
        // Проверяю соответствие логина и пароля, в случае неудачи показываю предупреждение
        if (viewModel.isEmailValid(email) && viewModel.isPasswordValid()) {
            // Произвожу регистрацию, в случае возврата перехожу на главную страницу, иначе
            // показываю соответствующее предупреждение
            viewModel.registrationUser(email, password) { authResult: Boolean ->
                // Использую обратный вызов для получения Task (результат регистрации),
                // поскольку регистрации производит асинхронно, путем обратного вызова
                if (authResult) {
                    findNavController().navigate(R.id.action_authenticationFragment_to_mainPageFragment)
                } else {
                    Toast.makeText(context,"Пользователь с указанным адресом электронной почты уже зарегистрирован!", Toast.LENGTH_SHORT).show()
                }
            }
        } else {
            Toast.makeText(context,"Пожалуйста, проверьте правильность введенных данных.", Toast.LENGTH_SHORT).show()
        }
    } else {
        Toast.makeText(context, "Пожалуйста, проверьте подключение к интернету и повторите попытку.", Toast.LENGTH_SHORT).show()
    }
}

ViewModel

fun registrationUser(email: String, password: String, lambda: (Boolean) -> Unit) {
    firebaseRepository.registrationUser(email, password, lambda)
}

FirebaseRepositoryImpl

override fun registrationUser(email: String, password: String, lambda: (Boolean) -> Unit) {
    authentication.createUserWithEmailAndPassword(email, password)
        .addOnCompleteListener { task: Task<AuthResult> ->
            if (task.isSuccessful) {
                addUserToDataBase(email)
                lambda.invoke(true)
            } else {
                lambda.invoke(false)
            }
        }
}

FirebaseRepository

fun registrationUser(email:String, password: String, lambda: (Boolean) -> Unit)

Считаю, что допустил ошибку, оставив внутри метода View такую логику. Думаю, что ее нужно перенести внутрь ViewModel, но возникает вопрос, как при этом оставить отображение предупреждений в виде Toast. Прошу указать на мои ошибки и дать советы, материалы для чтения, примеры по улучшению реализации.

Ответы

▲ 0Принят

все верно, это не MVVM. это просто использование ViewModel.
идея MVVM заключается в следующем:

любое действие из View - это вызов 1 метода ВьюМодели.
например, у вас есть кнопка, при нажатии на которую должно что-то измениться в 3 TextView. так вот листенер этой кнопки должен вызывать лишь 1 метод ViewModel, а не 3 для каждого TextView.
т.е. публичные методы ViewModel должны описывать действия пользователя.

получать результаты логической работы ViewModel напрямую, как вы, дергая методы нельзя!

их надо получать через специальных слушателей. сейчас на выбор 2 классных технологии: LiveData и Flow. я фанат LiveData и вам, для старта, тоже ее советую.
у вас хороший пример, чтобы разобраться в том, что такое SingleLiveEvent (кастомное решение для LiveData).

ваш код, должен выглядеть слеюущим образом:
внутри метода registrationUser должна быть лишь 1 строчка

viewModel.registrationUser(email, password)

внутри вьюмодель делает все валидации, которые ей надо, запросы в сеть или БД, включает / выключает значок загрузки (это тоже может быть подвязано на LiveData).
а ваша Вью лишь слушает эти LiveData.