如何在单独的存储库(MVVM)中传递 Firestore SnapshotListener 提供的实时数据
How to pass through livedata provided by Firestore SnapshotListener in a separate repository (MVVM)
经过几个小时的尝试和搜索,我仍然卡住了,希望有人能帮助我。
我试图通过我的 ViewModel 从 Firestore(使用 SnapshotListener)获取实时更新到我的 Activity,但我的所有尝试都失败了。以下是我当前的设置 - 尝试更新我的存储库中的 LiveData 并将其移交给视图模型...
我的问题:
我的 Firestore 集合中有 UserData(在文档中)。我尝试使用 observeUserData() 函数在运行时监听当前用户的变化。此函数提供的数据(关于文档更改)应通过我的 ViewModel 发送到我的 Activiy。如果我在 Firestore 中更改我的用户文档,SnapshotListener 会按预期触发,但更新没有到达我的 ViewModel,因此没有到达我的 Activity.
有人能帮我存档吗?我现在看到的唯一解决方案是在我的 ViewModel 中添加一个 SnapshotListener 但据我所知这是不好的做法吗?
非常感谢。
Firestore 存储库
object FirestoreService {
val db = FirebaseFirestore.getInstance()
val userDataLiveData = MutableLiveData<UserData>()
fun observeUserData(userId: String) {
try {
db.collection("userData").document(userId).addSnapshotListener{ documentSnapshot: DocumentSnapshot?, firebaseFirestoreException: FirebaseFirestoreException? ->
firebaseFirestoreException?.let {
Log.e(TAG, firebaseFirestoreException.toString())
return@addSnapshotListener
}
val data = documentSnapshot?.toUserData()
data?.let {
Log.d(TAG, "post new value")
userDataLiveData.postValue(data)
}
}
} catch (e: Exception) {
Log.e(TAG, "Error getting user data", e)
}
}
ViewModel
class MyViewModel (private val uid : String) : ViewModel() {
private var _userData = MutableLiveData<UserData>()
val userData: LiveData<UserData> = _userData
fun getUserData() {
Log.d(TAG, "getUserData called")
FirestoreService.observeUserData(uid)
var data = FirestoreService.userDataLiveData
_userData = data
}
}
Activity
//ViewModel Setup
val factory = MyViewModelFactory(user.uid.toString())
val viewModel = ViewModelProvider(this, factory).get(MyViewModel::class.java)
//Initialize UserData
viewModel.getUserData()
viewModel.userData.observe(this, Observer {
userData = it
Log.d(TAG, userData.toString())
})
您需要先初始化您的 viewModel
lateinit var userViewModel : MyViewModel
userViewModel = new ViewModelProvider(this).get(MyViewModel::class.java)
然后在您的 userViewModel 上使用 getViewLifeCycleOwner 方法,然后观察将包含您的 userDataModel 的 LiveData
您可以在 onChanged() 方法中访问 userDataModel 中的方法(getter 和 setter)
有一种更简单的方法可以做到这一点无需任何侦听器。首先,添加这个依赖:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.3.9"
然后假设您有以下存储库:
inteface FirestoreService {
fun sendUserData(uid: String): LiveData<String> // Or whatever it should emit
}
发出实时数据的实现可能如下:
class FirestoreServiceImpl : FireStoreService {
val db = FirebaseFirestore.getInstance()
fun sendUserData(uid: String): LiveData<String> = liveData {
val mySnapshot = db.collection("userData)".document(userId).await()
emit(mySnapshot?.toUserData)
}
}
如果想在viewModel中调用这个方法,最好把LiveData
改成Flow
fun sendUserData(uid: String): Flow<String> = flow {
val mySnapshot = db.collection("userData)".document(userId).await()
emit(mySnapshot?.toUserData)
}
在您的 ViewModel 中,您可以这样做:
val myInput = "TestUUID"
val myUserID = sendUserData(myInput).asLiveData()
然后,最后在片段/activity:
yourViewModel.myUserID.observe(viewLifecycleOwner) {
// do stuff here
}
谢谢大家的回复 - 幸运的是我在这个问题上找到了问题。
我想我混淆了太多来自不同“指南”/“方法”的东西 - 幸运的是我在下面找到了 Doug Stevenson 的精彩课程,这让我摆脱了这个:
https://www.youtube.com/watch?v=WXc4adLMDqk
谢谢道格 :)
经过几个小时的尝试和搜索,我仍然卡住了,希望有人能帮助我。 我试图通过我的 ViewModel 从 Firestore(使用 SnapshotListener)获取实时更新到我的 Activity,但我的所有尝试都失败了。以下是我当前的设置 - 尝试更新我的存储库中的 LiveData 并将其移交给视图模型...
我的问题: 我的 Firestore 集合中有 UserData(在文档中)。我尝试使用 observeUserData() 函数在运行时监听当前用户的变化。此函数提供的数据(关于文档更改)应通过我的 ViewModel 发送到我的 Activiy。如果我在 Firestore 中更改我的用户文档,SnapshotListener 会按预期触发,但更新没有到达我的 ViewModel,因此没有到达我的 Activity.
有人能帮我存档吗?我现在看到的唯一解决方案是在我的 ViewModel 中添加一个 SnapshotListener 但据我所知这是不好的做法吗? 非常感谢。
Firestore 存储库
object FirestoreService {
val db = FirebaseFirestore.getInstance()
val userDataLiveData = MutableLiveData<UserData>()
fun observeUserData(userId: String) {
try {
db.collection("userData").document(userId).addSnapshotListener{ documentSnapshot: DocumentSnapshot?, firebaseFirestoreException: FirebaseFirestoreException? ->
firebaseFirestoreException?.let {
Log.e(TAG, firebaseFirestoreException.toString())
return@addSnapshotListener
}
val data = documentSnapshot?.toUserData()
data?.let {
Log.d(TAG, "post new value")
userDataLiveData.postValue(data)
}
}
} catch (e: Exception) {
Log.e(TAG, "Error getting user data", e)
}
}
ViewModel
class MyViewModel (private val uid : String) : ViewModel() {
private var _userData = MutableLiveData<UserData>()
val userData: LiveData<UserData> = _userData
fun getUserData() {
Log.d(TAG, "getUserData called")
FirestoreService.observeUserData(uid)
var data = FirestoreService.userDataLiveData
_userData = data
}
}
Activity
//ViewModel Setup
val factory = MyViewModelFactory(user.uid.toString())
val viewModel = ViewModelProvider(this, factory).get(MyViewModel::class.java)
//Initialize UserData
viewModel.getUserData()
viewModel.userData.observe(this, Observer {
userData = it
Log.d(TAG, userData.toString())
})
您需要先初始化您的 viewModel
lateinit var userViewModel : MyViewModel
userViewModel = new ViewModelProvider(this).get(MyViewModel::class.java)
然后在您的 userViewModel 上使用 getViewLifeCycleOwner 方法,然后观察将包含您的 userDataModel 的 LiveData
您可以在 onChanged() 方法中访问 userDataModel 中的方法(getter 和 setter)
有一种更简单的方法可以做到这一点无需任何侦听器。首先,添加这个依赖:
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-play-services:1.3.9"
然后假设您有以下存储库:
inteface FirestoreService {
fun sendUserData(uid: String): LiveData<String> // Or whatever it should emit
}
发出实时数据的实现可能如下:
class FirestoreServiceImpl : FireStoreService {
val db = FirebaseFirestore.getInstance()
fun sendUserData(uid: String): LiveData<String> = liveData {
val mySnapshot = db.collection("userData)".document(userId).await()
emit(mySnapshot?.toUserData)
}
}
如果想在viewModel中调用这个方法,最好把LiveData
改成Flow
fun sendUserData(uid: String): Flow<String> = flow {
val mySnapshot = db.collection("userData)".document(userId).await()
emit(mySnapshot?.toUserData)
}
在您的 ViewModel 中,您可以这样做:
val myInput = "TestUUID"
val myUserID = sendUserData(myInput).asLiveData()
然后,最后在片段/activity:
yourViewModel.myUserID.observe(viewLifecycleOwner) {
// do stuff here
}
谢谢大家的回复 - 幸运的是我在这个问题上找到了问题。
我想我混淆了太多来自不同“指南”/“方法”的东西 - 幸运的是我在下面找到了 Doug Stevenson 的精彩课程,这让我摆脱了这个:
https://www.youtube.com/watch?v=WXc4adLMDqk
谢谢道格 :)