Как обновить вид после данных, полученных от подписки на наблюдаемую?

Я использую 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());
}

Это из-за CalledFromWrongThreadException при выполнении this::displayCharacteristics, Как правильно отобразить данные в потоке, в котором находится фрагмент? Должен ли я использовать слушателя? Спасибо!

2 ответа

Решение

Для взаимодействия с пользовательским интерфейсом в ОС Android вам необходимо находиться в главном потоке. Когда имеешь дело с RxJava Вы можете сделать это легко, добавив строку .observeOn(AndroidSchedulers.mainThread()),

По версии 1.4.0RxAndroidBle не имеет переходной зависимости от RxAndroid библиотека больше. Использовать AndroidSchedulers класс вам нужно добавить зависимость самостоятельно в build.gradle файл:

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

RxAndroidBle библиотека сама обрабатывает потоки команд BLE, поэтому нет необходимости использовать .subscribeOn(Schedulers.io()) поскольку выполнение будет быстро передано фоновому потоку.

Ваш код может выглядеть так, чтобы работать с пользовательским интерфейсом:

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);
}

Вы хотите обработать свои данные в потоке ввода-вывода и отправленные данные обратно в потоке пользовательского интерфейса.

Вы можете сделать это с помощью этих планировщиков.

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() везде и обрабатывать их в вашем подписчике (как вы уже сделали)

Другие вопросы по тегам