如何在从 observable 上的订阅接收到数据后更新视图?

How to update view after data received from subscribe on an observable?

我正在为一个项目使用 RxAndroidBle,我需要从蓝牙设备读取一些特性,然后将它们显示在屏幕上。以下代码适用于 this::displayCharacteristics

private void readCharacteristics() {
    mConnectionObservable.flatMap(rxBleConnection -> Observable.combineLatest(
            rxBleConnection.readCharacteristic(UUID_SERIAL_NUMBER),
            rxBleConnection.readCharacteristic(UUID_MACHINE_TYPE),
            rxBleConnection.readCharacteristic(UUID_CHARACTERISTIC),
            ConnectedViewModel::new
            ).doOnError(this::logError)
    ).doOnError(this::logError)
    .subscribe(this::displayCharacteristics, this::logError);
}


private void displayCharacteristics(ConnectedViewModel model) {
    mSerialNumber.setText(model.getSerialNumber());
    mMachineType.setText(model.getMachineType());
    mCableLength.setText(model.getCableLength());
    mCableSize.setText(model.getCableSize());
    mUnits.setText(model.getUnits());
}

这是因为执行this::displayCharacteristics时出现了CalledFromWrongThreadException。在片段所在的线程上显示数据的正确方法是什么?我必须使用监听器吗?谢谢!

您想在 IO 线程中处理您的数据,并在 UI 线程中处理返回的数据。

您可以使用那些调度程序来做到这一点。

private void readCharacteristics() {
    mConnectionObservable.flatMap(rxBleConnection -> Observable.combineLatest(
            rxBleConnection.readCharacteristic(UUID_SERIAL_NUMBER),
            rxBleConnection.readCharacteristic(UUID_MACHINE_TYPE),
            rxBleConnection.readCharacteristic(UUID_CHARACTERISTIC),
            ConnectedViewModel::new
            ).doOnError(this::logError)
    ).doOnError(this::logError)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(this::displayCharacteristics, this::logError);
}

您还应该避免在任何地方使用所有这些 .doOnError() 并在您的订阅者中处理它(正如您已经完成的那样)

要与 Android OS 上的 UI 交互,您需要在主线程上。在处理 RxJava 时,您可以通过添加一行 .observeOn(AndroidSchedulers.mainThread()).

轻松做到这一点

从版本 1.4.0 开始,RxAndroidBle 不再对 RxAndroid 库具有传递依赖性。要使用 AndroidSchedulers class 你需要自己在 build.gradle 文件中添加一个依赖:

dependencies {
    compile 'io.reactivex:rxandroid:1.2.1'
}

RxAndroidBle 库自行处理 BLE 命令的线程,因此几乎不需要使用 .subscribeOn(Schedulers.io()),因为执行将很快移交给后台线程。

您的代码可以像这样使用 UI:

private void readCharacteristics() {
    mConnectionObservable.flatMap(rxBleConnection -> Observable.combineLatest(
            rxBleConnection.readCharacteristic(UUID_SERIAL_NUMBER),
            rxBleConnection.readCharacteristic(UUID_MACHINE_TYPE),
            rxBleConnection.readCharacteristic(UUID_CHARACTERISTIC),
            ConnectedViewModel::new
        )
        .doOnError(this::logError)
    )
    .doOnError(this::logError)
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(this::displayCharacteristics, this::logError);
}