【问题标题】:How to observe data inside viewmodel?如何观察视图模型中的数据?
【发布时间】:2020-12-22 09:01:14
【问题描述】:

我已将我的 android 应用程序连接到 firebase,并使用它从 firestone 检索身份验证详细信息和数据。我为此使用了 MVVM 架构和实时数据。问题是我需要先检索电子邮件地址,然后使用此数据查询包含 ID = emailID 文档的 firestone。你可以看到我的视图模型。每次我运行它时,emailID 的值都是空的。在遵循 MVVP 编码风格的同时,我怎样才能做到这一点?

#Edit:我需要了解在一个 livedata 值依赖于另一个值的情况下,如何检查实时数据是否已用某个值初始化。

class ProfileViewModel(): ViewModel() {

    var random =""
    private var _name = MutableLiveData<String>()
    val userName
        get()=_name

    private  var _post = MutableLiveData<String>()
    val userPost
        get()=_post

    private var _imgUrl = MutableLiveData<Uri>()
    val userImgUrl
        get()=_imgUrl

    private var _emailId = MutableLiveData<String>()
    val userEmailId
        get()=_emailId


    init{

        getUserDataFromProfile()
        getUserPostFromFirestone()

    }

    private fun getUserPostFromFirestone() {


        val mDatabaseInstance: FirebaseFirestore = FirebaseFirestore.getInstance()
//        _emailId.observe(getApplication(), Observer {
//
//        } )
        if(_emailId.value!=null){
            mDatabaseInstance.collection("users").document(_emailId.value)
                .get()
                .addOnCompleteListener { task ->
                    if (task.isSuccessful) {
                        _post.value = task.result?.data?.get("post").toString()

                    } else {
//                    Log.w("firestone", "Error getting documents.", task.exception)
                        _post.value = "Unable to Retrieve"
                    }
                }
        }
    }

    private fun getUserDataFromProfile() {

        val mAuth = FirebaseAuth.getInstance()

        val currentUser = mAuth.currentUser
        random = currentUser?.displayName!!
        _name.value = currentUser?.displayName

        _post.value = "Unknown"
        _imgUrl.value = currentUser?.photoUrl
        _emailId.value = currentUser?.email


    }


}

【问题讨论】:

  • 你不必观察。在if (task.isSuccessful) 内调用getUserDataFromProfile。您还想考虑为 Livedata 类型使用 Wrapper 资源,否则您将如何检查其状态 Success fail 或 In progress ?
  • 我明白这一点。我打算把它转换成协程。

标签: android android-livedata android-mvvm


【解决方案1】:

如果您在 Firebase 调用上编写一个包装器并将其公开为 LiveData(或者,在这种情况下,我会假装它被包装在 suspendCoroutineCancellable 中),在这种情况下,无论何时您想要链接内容,您要么需要 MediatorLiveData 将多个 LiveData 组合成一个流(参见 this library I wrote for this specific purpose)或只是 switchMap

private val auth = FirebaseAuth.getInstance()

val imgUrl: LiveData<Uri> = MutableLiveData<Uri>(auth.currentUser?.photoUrl)
val emailId: LiveData<String> = MutableLiveData<String>(auth.currentUser?.email)

val post = emailId.switchMap { emailId -> 
    liveData {
        emit(getUserByEmailId(emailId))
    }
}

【讨论】:

    【解决方案2】:

    您可以将observer 设置为LiveData 并在不需要时将其删除:

    class ProfileViewModel : ViewModel() {
    
        private val _email = MutableLiveData<String>()
    
        private val emailObserver = Observer<String> { email ->
            //email is here
        }
    
        init {
            _email.observeForever(emailObserver)
        }
    
        override fun onCleared() {
            _email.removeObserver(emailObserver)
            super.onCleared()
        }
    }
    

    【讨论】:

      【解决方案3】:

      尝试使用协程来顺序执行代码。所以一旦你得到一个的输出,然后第二个开始执行。如果这不起作用,请告诉我,我可以尝试帮助你。

       init{
          viewModelScope.launch{
                  getUserDataFromProfile()
                  getUserPostFromFirestone()
          }
         }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-07
        • 1970-01-01
        • 2017-02-19
        • 2018-05-13
        • 1970-01-01
        • 2019-06-05
        • 2020-10-04
        • 2017-09-15
        相关资源
        最近更新 更多