我正在使用“ 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)
此代码应在后台线程中。 但事实并非如此。 我该怎么办?
答案 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())
}
}