当前位置: 首页 > 知识库问答 >
问题:

插入时多次触发Room RxJava observable

呼延高超
2023-03-14

我的存储库实现遇到了一个奇怪的问题。每次调用应该从数据库获取数据并通过网络调用更新数据库的函数时,我都会从数据库观察器收到多个结果。

override fun getApplianceControls(
    serialNumber: SerialNumber
): Flowable<ApplianceControlState> {
    val subject = BehaviorProcessor.create<ApplianceControlState>()

    controlsDao.get(serialNumber.serial)
        .map { controls ->
            ApplianceControlState.Loaded(controls.toDomainModel())
        }
        .subscribe(subject)

    controlApi.getApplianceControls(serialNumber.serial)
        .flatMapObservable<ApplianceControlState> { response ->
            val entities = response.toEntity(serialNumber)
            // Store the fetched controls on the database.
            controlsDao.insert(entities).andThen(
                // Return an empty observable because the db will take care of emitting latest values.
                Observable.create { }
            )
        }
        .onErrorResumeNext { error: Throwable ->
            Observable.create { emitter -> emitter.onNext(ApplianceControlState.Error(error)) }
        }
        .subscribeOn(backgroundScheduler)
        .subscribe()


    return subject.distinctUntilChanged()
}
kotlin prettyprint-override">@Dao
interface ApplianceControlsDao {

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun insert(controls: List<TemperatureControlEntity>): Completable

    @Query("SELECT * FROM control_temperature WHERE serial = :serial")
    fun get(serial: String): Flowable<List<TemperatureControlEntity>>
}

基本上,如果我调用一次GetApplianceControl,就会得到所需的结果。然后我再次调用另一个序列号,它是空的,我得到了空数组。但是,我第三次调用,但是使用与第一次相同的序列号,在进行insert调用后,我得到了正确结果和空数组的混合。

像这样:

第一次呼叫,序列号“123”-

第二次呼叫,序列号“000”-

第三次呼叫,序列号“123”-

如果我从api响应中删除db插入,它会正常工作。调用插入后发生一切奇怪的事情。

编辑:从视图模型调用GetApplianceControl()

fun loadApplianceControls(serialNumber: SerialNumber) {
    Log.i("Loading appliance controls")

    applianceControlRepository.getApplianceControls(serialNumber)
        .subscribeOn(backgroundScheduler)
        .observeOn(mainScheduler)
        .subscribeBy(
            onError = { error ->
                Log.e("Error $error")
            },
            onNext = { controlState ->
                _controlsLiveData.value = controlState  
            }
        ).addTo(disposeBag)
}

共有1个答案

罗波鸿
2023-03-14

正如我在评论中提到的,您有两个订阅,但都没有在任何地方取消订阅,这可能会导致内存泄漏(当主题被释放时,它不会被释放),而且在这种实现中,您会忽略API错误。我会尝试将其改为:

override fun getApplianceControls(serialNumber: SerialNumber): Flowable<ApplianceControlState> {

    val dbObservable = controlsDao.get(serialNumber.serial)
        .map { controls ->
            ApplianceControlState.Loaded(controls.toDomainModel())
        }

    val apiObservable = controlApi.getApplianceControls(serialNumber.serial)
        .map { response ->
            val entities = response.toEntity(serialNumber)
           // Store the fetched controls on the database.
           controlsDao.insert(entities).andThen( Unit )
        }
        .toObservable()
        .startWith(Unit)

    return Observables.combineLatest(dbObservable, apiObservable) { dbData, _ -> dbData }
        // apiObservable emits are ignored, but it will by subscribed with dbObservable and Errors are not ignored 
        .onErrorResumeNext { error: Throwable ->
            Observable.create { emitter -> emitter.onNext(ApplianceControlState.Error(error)) }
        }
        .subscribeOn(backgroundScheduler)
        //observeOn main Thread
        .distinctUntilChanged()
}

我不确定它是否解决了最初的问题。但如果是这样-问题在平面地图观察ALSO将有助于查看ControlApi.getApplianceControlls()实现。

 类似资料:
  • 谁能帮我创建一个触发器,将Sensordata表中的最后一条记录附加到lastssensordata中。我只希望每个ConnectionDeviceId有1个值,并且该值必须是最后插入的值。(它将用于在仪表中显示)。我将在下链接我的sql脚本。

  • 在firebase文档之后构建一个存在的应用程序,有没有这样一个场景,当应用程序仍然连接时,on-disconnect会触发?我们看到存在节点显示应用程序离线,然后在几秒钟内恢复在线,而我们没有失去网络连接。 我们在安装在现场的多个嵌入式设备上看到,存在设置为false,然后几乎立即恢复为true,并且在几秒钟内发生在所有设备上。从我们所做的测试和在线文档中,我们知道如果我们在设备上失去互联网连接

  • null 计划:当用户购买一张票时,我将一条记录插入到适当的表中。例如,如果用户购买: Ticket#1,我将一条记录插入Table1 Ticket#2,我将一条记录插入Table1和Table2 Ticket#3,我将一条记录插入Table1和Table3 问题:如何接收不是类型为1的票证的所有数据,然后拆分参数插入到单独的表中。例如,当我试图为Table2创建触发器时,该触发器只能接收与Tab

  • 问题内容: 我知道这个问题已经被问过多次了,但是没有人能够从我所看到的问题中得出一个可行的答案。 我正在开发一个应用程序以拦截短信,并根据发送的#弹出自定义提醒。我让它与广播接收器完美配合,但是,如果用户安装了goSms,则永远不会调用该方法,因为goSms在它到达我的应用程序之前会中止它。 为了解决这个问题,我尝试在内容观察器上 正常工作,但是使用相同的参数调用了两次。香港专业教育学院试图检查时

  • 我刚开始流口水,遇到了一个问题。 我简化了规则以显示问题: 基本上,我想计算特定路段上发生的事件(路段是道路的一部分)。当同一链接上发生3个事件时,我希望触发规则。 上面的规则几乎起作用了,但是当它发射时,它发射了3次,每个事件发射一次。我只希望它发射一次。 我错过了什么? 非常感谢。

  • 我对TextWatcher有一个恼人的问题。我一直在网上搜索,但什么也找不到。如果有人能帮助我,我将不胜感激。 由于某些原因,在一次文本更改时对TextWatcher事件的调用是不稳定的。有时它们被触发一次(就像它们应该被触发的那样),有时两次,有时三次。不知道为什么,整个事情都很直截了当。有时,PostTextChanged()上的可编辑参数在toString()和length()中返回空值。