回调流等待收集其内部流

发布于 2025-02-11 13:26:56 字数 4965 浏览 1 评论 0原文

我正在我的Android应用程序中实现Firestore,我想知道如何使该代码在使用该程序之前等待其内部流程。 Trip.tripdays在wher表达式中的响应之后的时间填充了数据。

override fun getTrips(idUser: String): Flow<Response<List<Trip>>> = callbackFlow {
        val trips = mutableListOf<Trip>()
        tripsRef
            .whereEqualTo(ID_USER, idUser)
            .get()
            .addOnSuccessListener { snapshot ->
                for (doc in snapshot.documents) {
                    val trip = doc.toObject(Trip::class.java)
                    if (trip != null) {
                        trip.id = doc.id
                        CoroutineScope(Dispatchers.IO).launch {
                            val tripDaysFlow = tripDaysRepository.getTripDays(trip.id)
                            tripDaysFlow.collect() {
                                when (it) {
                                    is Response.Loading -> {
                                        Log.d("FirestoreTripsRepositoryImpl", "Loading")
                                    }
                                    is Response.Success -> {
                                        trip.tripDays = it.data
                                    }
                                    is Response.Error -> {
                                        trySend(Response.Error(it.message)).isFailure
                                    }
                                    is Response.Message -> {
                                        trySend(Response.Message(it.message))
                                    }
                                }
                            }
                        }
                        trips.add(trip)
                    }
                }
                trySend(Response.Success(trips)).isSuccess
            }
            .addOnFailureListener {
                trySend(Response.Error(it.message ?: it.toString())).isFailure
            }
            .await()
        awaitClose()
    }
override fun getTripDays(idTrip: String): Flow<Response<List<TripDay>>> = callbackFlow {
        val tripDaysRef = tripsRef.document(idTrip).collection(TRIP_DAYS_REF)
        val tripDays = mutableListOf<TripDay>()
        tripDaysRef
            .get()
            .addOnSuccessListener {
                for (doc in it.documents) {
                    val tripDay = doc.toObject(TripDay::class.java)
                    if (tripDay != null) {
                        tripDay.id = doc.id
                        tripDays.add(tripDay)
                    }
                }
                trySend(Response.Success(tripDays)).isSuccess
            }
            .addOnFailureListener {
                trySend(Response.Error(it.message ?: it.toString())).isFailure
            }
            .await()
        awaitClose ()
    }
sealed class Response<out T> {
    object Loading : Response<Nothing>()
    data class Success<out T>(val data: T) : Response<T>()
    data class Error(val message: String) : Response<Nothing>()
    data class Message(val message: String) : Response<Nothing>()
}

一个很大的发射:

override fun getTrips(idUser: String): Flow<Response<List<Trip>>> = callbackFlow {
        val trips = mutableListOf<Trip>()
        tripsRef
            .whereEqualTo(ID_USER, idUser)
            .get()
            .addOnSuccessListener { snapshot ->
                launch {
                    Log.d("launch", "launched")
                    for (doc in snapshot.documents) {
                        if (doc.id == "kJJFEatove5mxw4P70uq")
                            continue
                        val trip = doc.toObject(Trip::class.java)
                        if (trip != null) {
                            trip.id = doc.id
                            val tripDaysFlow = tripDaysRepository.getTripDays(trip.id)
                            tripDaysFlow.collect {
                                when (it) {
                                    is Response.Loading -> trySend(Response.Loading)
                                    is Response.Success -> trip.tripDays = it.data
                                    is Response.Error -> trySend(Response.Error(it.message)).isFailure
                                    is Response.Message -> trySend(Response.Message(it.message))
                                }
                            }
                            trips.add(trip)
                        }
                    }
                    trySend(Response.Success(trips)).isSuccess
                    close()
                }
            }
            .addOnFailureListener {
                trySend(Response.Error(it.message ?: it.toString())).isFailure
                close()
            }
        awaitClose()
    }

可以使它在没有完整的重建的情况下使其正常工作会很酷,但是让我知道我的方法是否完全错误。干杯!

I'm implementing firestore in my android app and I was wondering how I can make this code wait for its inner flow to be collected before running with the program. The trip.tripDays in the when expression is getting populated with data a time after Response.Success with my trips is already sent.

override fun getTrips(idUser: String): Flow<Response<List<Trip>>> = callbackFlow {
        val trips = mutableListOf<Trip>()
        tripsRef
            .whereEqualTo(ID_USER, idUser)
            .get()
            .addOnSuccessListener { snapshot ->
                for (doc in snapshot.documents) {
                    val trip = doc.toObject(Trip::class.java)
                    if (trip != null) {
                        trip.id = doc.id
                        CoroutineScope(Dispatchers.IO).launch {
                            val tripDaysFlow = tripDaysRepository.getTripDays(trip.id)
                            tripDaysFlow.collect() {
                                when (it) {
                                    is Response.Loading -> {
                                        Log.d("FirestoreTripsRepositoryImpl", "Loading")
                                    }
                                    is Response.Success -> {
                                        trip.tripDays = it.data
                                    }
                                    is Response.Error -> {
                                        trySend(Response.Error(it.message)).isFailure
                                    }
                                    is Response.Message -> {
                                        trySend(Response.Message(it.message))
                                    }
                                }
                            }
                        }
                        trips.add(trip)
                    }
                }
                trySend(Response.Success(trips)).isSuccess
            }
            .addOnFailureListener {
                trySend(Response.Error(it.message ?: it.toString())).isFailure
            }
            .await()
        awaitClose()
    }
override fun getTripDays(idTrip: String): Flow<Response<List<TripDay>>> = callbackFlow {
        val tripDaysRef = tripsRef.document(idTrip).collection(TRIP_DAYS_REF)
        val tripDays = mutableListOf<TripDay>()
        tripDaysRef
            .get()
            .addOnSuccessListener {
                for (doc in it.documents) {
                    val tripDay = doc.toObject(TripDay::class.java)
                    if (tripDay != null) {
                        tripDay.id = doc.id
                        tripDays.add(tripDay)
                    }
                }
                trySend(Response.Success(tripDays)).isSuccess
            }
            .addOnFailureListener {
                trySend(Response.Error(it.message ?: it.toString())).isFailure
            }
            .await()
        awaitClose ()
    }
sealed class Response<out T> {
    object Loading : Response<Nothing>()
    data class Success<out T>(val data: T) : Response<T>()
    data class Error(val message: String) : Response<Nothing>()
    data class Message(val message: String) : Response<Nothing>()
}

One big launch:

override fun getTrips(idUser: String): Flow<Response<List<Trip>>> = callbackFlow {
        val trips = mutableListOf<Trip>()
        tripsRef
            .whereEqualTo(ID_USER, idUser)
            .get()
            .addOnSuccessListener { snapshot ->
                launch {
                    Log.d("launch", "launched")
                    for (doc in snapshot.documents) {
                        if (doc.id == "kJJFEatove5mxw4P70uq")
                            continue
                        val trip = doc.toObject(Trip::class.java)
                        if (trip != null) {
                            trip.id = doc.id
                            val tripDaysFlow = tripDaysRepository.getTripDays(trip.id)
                            tripDaysFlow.collect {
                                when (it) {
                                    is Response.Loading -> trySend(Response.Loading)
                                    is Response.Success -> trip.tripDays = it.data
                                    is Response.Error -> trySend(Response.Error(it.message)).isFailure
                                    is Response.Message -> trySend(Response.Message(it.message))
                                }
                            }
                            trips.add(trip)
                        }
                    }
                    trySend(Response.Success(trips)).isSuccess
                    close()
                }
            }
            .addOnFailureListener {
                trySend(Response.Error(it.message ?: it.toString())).isFailure
                close()
            }
        awaitClose()
    }

Would be cool to make it work without a complete rebuild, but let me know if my approach is completely wrong. Cheers!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文