Как наблюдать LiveData из репозитория? - PullRequest
1 голос
/ 24 января 2020

Я бы хотел получить пользователя из моей базы данных комнат с помощью репозитория, а затем наблюдать за ним во фрагменте OverviewFragment.

Что я пробовал:

  • с использованием Observer во фрагменте, но я получил исключение NullPointerException.

  • с использованием @{overviewViewModel.user.email} во фрагменте_overview. xml: приложение работает, но ничего не отображается.

  • Модульное тестирование и инструментальное тестирование с помощью FakeRepository. Тесты пройдены, и данные отображаются.

Что я использую:

  • Android Studio (до дата)

  • Kotlin

  • Архитектура MVVM

  • Шаблон репозитория, связанный с базой данных Room

  • Внедрение зависимостей в конструктор (для моделей представления)

  • ServiceLocator шаблон для тестирования

Поток пользователей (навигация)

Пользователь открывает приложение, заполняет форму и нажимает кнопку регистрации в элементе RegistrationFragment, затем переходит к элементу OverviewFragment, где находятся его данные (электронная почта , Пароль).

RegistrationViewModel:

class RegistrationViewModel(private val repository: IUserRepository) : ViewModel() {

    private var viewModelJob = Job()
    private val uiScope = CoroutineScope(Dispatchers.Main +  viewModelJob)

    private val _user = MutableLiveData<User>()

    val user: LiveData<User>
        get() = _user

    val email = MutableLiveData<String>()
    val password = MutableLiveData<String>()

    [...]

    fun onRegister() {

        val userEmail = email.value.toString()
        val userPassword = password.value.toString()

        registerUser(User(userEmail, userPassword))
    }

    private fun registerUser(newUser: User) = uiScope.launch {
        repository.registerUser(newUser)
    }

    [...]
}

OverviewViewModel

class OverviewViewModel(val database: UserDatabaseDao,
                        private val userRepository: IUserRepository
) : ViewModel() {

    private val _user = MutableLiveData<User>()

    val user: LiveData<User>
        get() = _user

    init {
        getUser()
    }

    private fun getUser() {
        runBlocking {_user.value = userRepository.getUser().value }
    }

OverviewFragment:

class OverviewFragment : Fragment() {

[...]
        overviewViewModel.user.observe(this, Observer {
                binding.apply {
                    textview.text = overviewViewModel.user.value!!.email
                    textview2.text = overviewViewModel.user.value!!.password
                }
        })
        return binding.root
    }
}

Репозиторий:

class UserRepository(private val dataSource: UserDatabaseDao,
                     private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO) :
    IUserRepository {

    override suspend fun registerUser(user: User) = withContext(ioDispatcher) {
        dataSource.insert(user)
    }

    override suspend fun getUser(): LiveData<User?> = withContext(ioDispatcher) {
        return@withContext dataSource.getUser()
    }

    override suspend fun getUser(email: String): LiveData<User?> = withContext(ioDispatcher) {
        return@withContext dataSource.getUser(email)
    }
}

DatabaseDao:

@Dao
interface UserDatabaseDao {

    @Insert
    fun insert(user: User)

    @Query("SELECT * from user_table WHERE email = :key")
    fun getUser(key: String): LiveData<User?>

    @Query("SELECT * from user_table")
    fun getUser(): LiveData<User?>

    @Query("SELECT * from user_table")
    fun getAllUsers(): LiveData<List<User>>

}

Примечание: есть только один пользователь в базе данных, один заполняет форму в регистрационном фрагменте.

...