LiveData не работает при хранении в ViewModel - PullRequest
0 голосов
/ 09 мая 2020

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

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

Я предполагаю, что это связано с тем, что Observer никогда не получал правильного значения, но как это могло произойти?

ProfileFragment

viewModel.getUserData вызывается onViewCreated, и каждый раз, когда пользователь завершает редактирование своих данных / информации профиля

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        viewModel = ViewModelProvider.AndroidViewModelFactory(activity!!.application).create(AboutViewModel::class.java)

        viewModel.getUserData()
        viewModel.userDataLiveData.observe(viewLifecycleOwner, Observer {
            when (it) {
                is Resource.Success -> {
                    text_account_name.text = it.data.name
                    text_account_email.text = it.data.email
                    text_account_phone_number.text = it.data.phoneNumber
                }
                is Resource.Failure -> {
                    when (it.throwable) {
                        is UserDataEmptyException -> startFillDataActivity()
                    }
                }
            }
        })
    }

ViewModel

var userDataLiveData: LiveData<Resource<User>> = MutableLiveData()
fun getUserData() {
        userDataLiveData = DatabaseRepository.getUserData(uid)
    }

Репозиторий базы данных

fun getUserData(uid: String): LiveData<Resource<User>>{
        val result = MutableLiveData<Resource<User>>().apply {
            value = Resource.Loading()
        }

        userRef.child(uid).addListenerForSingleValueEvent(object : ValueEventListener{
            override fun onDataChange(p0: DataSnapshot) {
                val name = p0.child(FIELD_NAME).value.toString()
                val email = p0.child(FIELD_EMAIL).value.toString()
                val phoneNumber = p0.child(FIELD_PHONE_NUMBER).value.toString()
                val user = User(name, email, phoneNumber)

                if(checkIfUserDataComplete(user)) result.value = Resource.Success(user)
                else result.value = Resource.Failure(UserDataEmptyException("User have no data"))
            }

            override fun onCancelled(p0: DatabaseError) {
                result.value = Resource.Failure(p0.toException())
            }
        })

        return result
    }

Ответы [ 3 ]

0 голосов
/ 09 мая 2020

MustafaKhaled Не думаю, что это проблема. viewmodelfactory должен возвращать тот же экземпляр viewmodel, это не имеет значения при выполнении. Собственно, именно поэтому мы используем этого провайдера.

Я думаю, вы можете найти решение реальной проблемы здесь:

Разница между addValueEventListener () и addListenerForSingleValueEvent () из firebase

0 голосов
/ 09 мая 2020

Послушайте, в вашем коде есть проблема: вызов viewModel.getUserData () изменяет ссылку на userDataLiveData. Итак, сначала вы начинаете наблюдать живые данные, созданные при первом вызове. Но после следующего вызова вы создаете другие живые данные. И вы будете обновлять значения этих новых данных в реальном времени, но продолжаете наблюдать за старыми.

Вы должны продолжать использовать те же данные в реальном времени, например, Repository

private val result: LiveData<Resource<User>> =  MutableLiveData<Resource<User>>()
fun getUserData(uid: String): LiveData<Resource<User>>{
        result.value = Resource.Loading()

        userRef.child(uid).addListenerForSingleValueEvent(object : ValueEventListener{
            override fun onDataChange(p0: DataSnapshot) {
                val name = p0.child(FIELD_NAME).value.toString()
                val email = p0.child(FIELD_EMAIL).value.toString()
                val phoneNumber = p0.child(FIELD_PHONE_NUMBER).value.toString()
                val user = User(name, email, phoneNumber)

                if(checkIfUserDataComplete(user)) result.value = Resource.Success(user)
                else result.value = Resource.Failure(UserDataEmptyException("User have no data"))
            }

            override fun onCancelled(p0: DatabaseError) {
                result.value = Resource.Failure(p0.toException())
            }

Viewmodel

getUserData() = DatabaseRepository.getUserData(uid)

Fragment

getUserData().observe...

Это быстрое решение с возможными рефакторами, но оно должно решить проблему.

0 голосов
/ 09 мая 2020

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

Вместо добавления:

        viewModel = ViewModelProvider.AndroidViewModelFactory(activity!!.application).create(AboutViewModel::class.java)

в ваш onViewCreated () добавьте его в onCreate () , чтобы ваша ViewModel инициализировалась один раз .

Попробуй, надеюсь поможет. Если не любезно прокомментируйте.

Удачного кодирования ?

...