База данных Firebase запрашивает пользователей в цикле

Например, у меня есть список проблем. Каждый выпуск имеет идентификатор владельца. По этому uid я должен найти нужного пользователя и отобразить его имя и фото. Я делаю это с помощью архитектурного компонента ViewModel:

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

        })
    }

Метод getIssueOwner:

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
}

Но я уверен, что такой подход неверен. Не могли бы вы дать мне совет, как мне построить архитектуру моего приложения?


person Ruslan Leshchenko    schedule 21.12.2017    source источник


Ответы (1)


Этот:

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

Дает точно такие же результаты, как это намного проще:

val userReference = usersReference.child(uid)

Единственная разница между ними заключается в том, что первый фрагмент дает вам снимок со списком одного элемента, а второй фрагмент дает вам снимок только с элементом.

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))
        }
    }
})

Обратите внимание, что вы по-прежнему не можете вернуть пользователя из метода getIssueOwner. Это связано с тем, что данные загружаются из Firebase асинхронно, и к моменту выполнения вашего оператора return оператор onDataChange еще не был вызван.

Я рекомендую вам прочитать несколько из этих предыдущих вопросов по этой теме, чтобы узнать больше об асинхронной природе Firebase (и большей части современной сети):

person Frank van Puffelen    schedule 21.12.2017
comment
Большое спасибо, возможно, вы знаете хороший способ выполнить запрос JOIN в Android, пожалуйста, помогите мне) - person Ruslan Leshchenko; 21.12.2017