# #android #kotlin #firebase-realtime-database #android-livedata #android-viewmodel
Вопрос:
У меня есть следующее data class
, в котором содержатся дочерние значения конкретной ссылки из базы данных Firebase в реальном времени:
data class Users(
val uid: String = "",
var firstName: String = "",
var lastName: String = "",
)
Это мой ViewModel
:
class UsersViewModel : ViewModel() {
private val uid = Firebase.auth.currentUser!!.uid
private val USERS_REF: DatabaseReference = FirebaseDatabase.getInstance().getReference("/users/$uid")
private val liveData: FirebaseQueryLiveData = FirebaseQueryLiveData(USERS_REF)
private val usersLiveData: MediatorLiveData<Users> = MediatorLiveData()
init {
usersLiveData.addSource(liveData, object : Observer<DataSnapshot> {
override fun onChanged(dataSnapshot: DataSnapshot?) {
if (dataSnapshot != null) {
usersLiveData.postValue(dataSnapshot.getValue(Users::class.java))
} else {
usersLiveData.value = null
}
}
})
}
@NonNull
fun getUsersLiveData() : LiveData<Users> {
return usersLiveData
}
}
Это мой расширенный LiveData
:
class FirebaseQueryLiveData(ref: DatabaseReference) : LiveData<DataSnapshot>() {
private val query: Query = ref
private val listener: MyValueEventListener = MyValueEventListener()
private var listenerRemovePending = false
private val removeListener = object : Runnable {
override fun run() {
query.removeEventListener(listener)
listenerRemovePending = false
}
}
override fun onActive() {
super.onActive()
if (listenerRemovePending) {
Handler(Looper.getMainLooper()).removeCallbacks(removeListener)
} else {
query.addValueEventListener(listener)
}
listenerRemovePending = false
}
override fun onInactive() {
super.onInactive()
Handler(Looper.getMainLooper()).postDelayed(removeListener, 2000)
query.removeEventListener(listener)
}
private inner class MyValueEventListener : ValueEventListener {
override fun onDataChange(snapshot: DataSnapshot) {
value = snapshot
}
override fun onCancelled(error: DatabaseError) {
return
}
}
}
Для считывания значений из моей базы данных в моей Activity
операционной Fragment
системе я сделал вот что:
val usersViewModel = ViewModelProvider(this).get(UsersViewModel::class.java)
val usersLiveData = usersViewModel.getUsersLiveData()
usersLiveData.observe(this, object : Observer<Users> {
override fun onChanged(users: Users?) {
if (users != null) {
firstNameTextView.text = users.firstName
lastNameTextView.text = users.lastName
}
}
})
Все это работает, но мой вопрос в том, как мне написать конкретному ребенку для моей базы данных в моем Activity
или Fragment
? Например, допустим, я хочу изменить только lastName
ребенка? Как мне это сделать? У меня нет никаких ссылок FirebaseDatabase
на мои действия и фрагменты, потому ViewModel
что и LiveData
убедитесь, что они мне больше не нужны.
Комментарии:
1. Вы можете перейти
lastName
от действия к модели просмотра после создания новой функции с логикой обновления базы данных, которая в данном случае является Firebase. Точно такgetUsersData
же , как вы можете создать новую функцию , скажемsetLastName
, у вас определенно есть модельDatabaseReference
представления, не так ли?2. И, насколько я знаю, Firebase не будет поддерживать
lastName
прямое редактирование, вам придется передать Firebase новуюUser
или любую другую вашу модель с обновленным значением свойства, а затем она соответствующим образом обновит ее3. Что вы до сих пор пробовали в коде для записи данных в базу данных?
4. @AlexMamo Перед использованием a
ViewModel
иLiveData
я бы написал данные следующим образом:Firebase.database.getReference("users").child(auth.currentUser!!.uid).child("lastName").setValue(newValue)
. Не уверен, как теперь будет работать запись данных в базу данных без ссылки на базу данных в моих действиях и фрагментах.5. @gtxtreme Да, у меня
DatabaseReference
в моемViewModel
, как вы можете видеть, он используется в основном конструкторе.