Я создаю приложение, которое использует GeoFirestore для выполнения запросов на основе местоположения элементов, хранящихся в базе данных firestore.У меня есть функция, которая получает список всех идентификаторов, которые соответствуют критериям местоположения:
private fun loadIds(location: Location, distance: Double): Single<List<String>> {
val query = geoFirestore.queryAtLocation(GeoPoint(location.latitude, location.longitude), distance)
val ids = ArrayList<String>()
return Single.create<List<String>> {
query.addGeoQueryEventListener(object : GeoQueryEventListener {
override fun onKeyEntered(uid: String, p1: GeoPoint?) {
ids.add(uid)
}
override fun onGeoQueryReady() {
it.onSuccess(ids)
}
override fun onKeyMoved(p0: String?, p1: GeoPoint?) {
}
override fun onKeyExited(p0: String?) {
}
override fun onGeoQueryError(p0: Exception?) {
}
})
}
}
, но теперь у меня возникают проблемы при попытке объединить результаты элементов из каждого идентификатора в Single<List<Item>>
каквозвращаемое значение.
Это то, что я делал раньше:
fun loadItems(ids: List<String>): Observable<Item> {
return Observable.create<Item> { emitter ->
for (id in ids) {
val reference = firestore.collection("items").document(id)
reference.get().addOnSuccessListener {
emitter.onNext(it.toObject(Item::class.java)!!)
if (ids.indexOf(id) == ids.size - 1) {
emitter.onComplete()
}
}
}
}
}
, где id был результатом loadIds()
.Это работало нормально, но в моей деятельности, где я это назвал, мне приходилось добавлять каждый элемент в упражнении по мере его выполнения, а затем прослушивать onComplete
, который иногда срабатывал до того, как все элементы были загружены.
Я пытаюсь улучшить свой код и дополнительно отделить логику базы данных от своей деятельности, поэтому я хочу иметь возможность вернуть Single<List<Item>>
, поэтому, как только я получу это в своей деятельности, я могу просто взять его изапустить.Я пытался понять это самостоятельно, но я довольно плохо знаком с RxJava и не совсем понимаю это.Вот моя последняя попытка:
fun loadItems(filter: Filter): Single<List<Item>> {
return Single.create<List<Item>> { emitter ->
val items= mutableListOf<Item>()
loadIds(filter.currentLocation, filter.distance).map {
for (uid in it) {
getItem(uid).map {item ->
items.add(item)
}.subscribe()
}
}.subscribe { _ ->
emitter.onSuccess(items)
}
}
}
private fun getItem(uid: String): Single<Item> {
return Single.create<Item> { emitter ->
firestore.collection("items").document(uid).get().addOnSuccessListener {
it.toObject(Item::class.java)?.let { item ->
emitter.onSuccess(item)
} ?: run {
emitter.onError(Throwable("Error finding item"))
}
}.addOnFailureListener {
emitter.onError(it)
}
}
}
, но, очевидно, onSuccess
вызывается почти сразу, поэтому я не получаю никаких результатов.