如何在嵌套代码中返回“ Observable / Flowable / Single”“ onError”?

时间:2018-07-19 16:28:27

标签: android firebase kotlin rx-java android-room

我正在使用“ RxJava”,“ Room”,“ Firebase(Firestore)”和“ Kotlin”开发一个Android应用。 它基于MVP模式。

我是RxJava的新手,所以我需要帮助... 对我来说很难...

情况是... 1.演示者请求用户访问DAO(本地数据库-会议室) 2. DAO返回一个用户  2.1如果不存在用户,则演示者请求用户使用Firebase(Firestore) 3.演示者使用户返回到视图。

代码在这里:

[1]道

@Dao
interface PlayersDao {
    @Query("SELECT * FROM player WHERE playerName = :playerName")
    fun getPlayerByName(playerName: String): Single<Player>
}

[2] Firebase

class FirebaseDataSource {
    private val mFirestore = FirebaseFirestore.getInstance()

    override fun getPlayerByName(playerName: String) = Single.create<Player> { emitter ->
        mFirestore.collection(PLAYERS)
            .whereEqualTo("playerName", playerName)
            .get()
            .addOnCompleteListener {
                if (it.isSuccessful && !it.result.isEmpty) {
                    emitter.onSuccess(it.result.documents[0].toObject(Player::class.java))
                } else {
                    emitter.onError(PlayerNotExistException())
                }
            }
    }
}

[3]演示者

fun getPlayer(playerName: String): Single<Player> {
    return Single.create { emitter ->
        playerDao.getPlayerByName(playerName)
            .doOnError {
                // When it failed to get the user from local, it should retry to Firebase.
                // But I don't know how should I cover this logic.
                Single.create<Player> { emitter2 ->
                    firebaseDataSource.getPlayerByName(playerName)
                        .doOnError {
                            Log.d(TAG, "getPlayerByName(firebase) - failed")
                        }
                        .doOnSuccess {
                            emitter.onSuccess(it)
                        }
                    }
                }
                .doOnSuccess {
                    Log.d(TAG, "getPlayerByName(local) - success")
                    emitter.onSuccess(it)
                }
    }
}

当从本地数据库获取用户失败时,我不知道该如何获取并返回用户。

“单身”正确吗? 我应该使用“可观察”还是“可流动”?

<<< ------------------------艾哈迈德·阿什拉夫(Ahmed Ashraf G)将其清除。

这是一个连续的问题。 我修复了如下代码:

演示者

fun getPlayer(playerName: String): Single<Player> {
    Log.d(TAG, "getPlayerByName - $playerName")

    return playerDao.getPlayerByName(playerName)
            .onErrorResumeNext {
                Log.d(TAG, "[BS] getPlayerByName(local) - onError: ${it.message}")
                playersFirebaseDataSource.getPlayerByName(playerName)
                    .doOnSuccess {
                        Log.d(TAG, "getPlayerByName(firebase) - success")
                        playerDao.savePlayer(it) // Here is run in "Main" thread
                    }.subscribeOn(Schedulers.io())
            }
}
  

playerDao.savePlayer(it)

此代码应在后台线程中。 但事实并非如此。 我该怎么办?

2 个答案:

答案 0 :(得分:1)

您正在寻找“ onErrorResumeNext”运算符。 从文档中:

  

onErrorResumeNext()—指示Observable在遇到错误时发出一系列项目。

所以它可能看起来像这样:

return playerDao.getPlayerByName(playerName)
         .onErrorResumeNext(firebaseDataSource.getPlayerByName(playerName))

这基本上会尝试DAO单一文件,如果遇到错误,则会切换到FirebaseDataSource单一文件。

编辑:您可以在Here

中找到其他错误处理运算符

编辑2:关于第二个问题,您使用observeOn是正确的,这将在特定的调度程序上进行工作,但是您还使用了subscribeOn,这可能是有害的,这就是为什么,subscribeOn只能使用一次,它指定您将在其中“观察”可观察对象的线程,通常与AndroidSchedulers.mainThread()一起使用。

我建议通过Here

阅读有关该主题的更多信息

答案 1 :(得分:0)

为解决持续存在的问题,我自己修复了代码。

fun getPlayer(playerName: String): Single<Player> {
    return playerDao.getPlayerByName(playerName)
        .onErrorResumeNext {
            Log.d(TAG, "getPlayerByName(local) - onError: ${it.message}")
            playersFirebaseDataSource.getPlayerByName(playerName)
                .subscribeOn(Schedulers.io()) // I added this two line
                .observeOn(Schedulers.io())   // And it works fine.
                .doOnSuccess {
                    Log.d(TAG, "getPlayerByName(firebase) - success")
                    playerDao.savePlayer(it) // Now, here is run in the background thread!
                }.subscribeOn(Schedulers.io())
        }
}