0

For example, I have a list of issues. Each issue has owner uid. By this uid, I should find needed users and display his name and photo. I do it with help architecture component ViewModel:

 issues.forEach {
        IssueRepository().getIssueOwner(it.owner).observe(this, Observer {

        })
    }

getIssueOwner method:

fun getIssueOwner(uid: String): MutableLiveData<UserEntity> {
    val user: MutableLiveData<UserEntity> = MutableLiveData()
    val usersReference = FirebaseDatabase.getInstance().reference.child("users")
    val query = usersReference.orderByKey().equalTo(uid).limitToFirst(1)
    query.addValueEventListener(object : ValueEventListener {
        override fun onCancelled(p0: DatabaseError?) {
        }

        override fun onDataChange(dataSnapshot: DataSnapshot?) {
            if (dataSnapshot == null) {
                return
            }
            dataSnapshot.children.forEach {
                val name = it.child("displayName").value
                user.postValue(UserEntity(name))
            }

        }
    })
    return user
}

But I'm sure that this approach is not correct. Could you please give me an advice how I should build the architecture of my app?

Ruslan Leshchenko
  • 4,043
  • 4
  • 24
  • 36

1 Answers1

0

This:

val query = usersReference.orderByKey().equalTo(uid).limitToFirst(1)

Gives exactly the same results as this much simpler:

val userReference = usersReference.child(uid)

The only difference between the two is that the first snippet gives you a snapshot with a list of one item, while the second snippet gives you a snapshot with just the item.

val userReference = usersReference.child(uid)
userReference.addValueEventListener(object : ValueEventListener {
    override fun onCancelled(error: DatabaseError?) {
        throw error.toException() // don't ignore errors
    }

    override fun onDataChange(dataSnapshot: DataSnapshot?) {
        if (dataSnapshot.exists()
            val name = dataSnapshot.child("displayName").value
            user.postValue(UserEntity(name))
        }
    }
})

Note that you still can't return a user from the getIssueOwner method. This is because data is loaded from Firebase asynchronously, and by the time your return statement is executed, the onDataChange hasn't been called yet.

I recommend you read a few of these previous question on that topic to learn more about dealing with the asynchronous nature of Firebase (and most of the modern web):

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807