调试rxjava时出错CalledFromWrongThreadException

时间:2018-03-23 13:44:24

标签: android kotlin rx-java2

我有下一个代码。

private val observeRefresh = detailView.observeRefresh
            .observeOn(Schedulers.io())
            .map { _ -> detailModel.forecastCity }
            .flatMap { city ->
                detailModel.getForecast(city.id, FORECAST_COUNT)
                        .map { response -> DetailUiModel.stateSuccess(response.list, detailModel.forecastCity) }
                        .onErrorReturn { t -> DetailUiModel.stateError(t.message) }
                        .observeOn(AndroidSchedulers.mainThread())
                        .startWith(DetailUiModel.stateLoading)
            }
            .subscribe { this.handleResponse(it) }


private fun handleResponse(model: DetailUiModel) {
        detailView.setLoading(model.isLoading)
        when {
            model.success -> detailView.setForecastItems(model.data!!)
            !model.isLoading -> detailView.showError(model.error)
            model.city != null -> detailView.setMapImage(createMapUrl(model.city!!))
            else -> return
        }

    }

我想调试此行detailView.setMapImage(createMapUrl(model.city!!))当我添加检查点应用程序时抛出错误CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views. 如果我没有添加检查点应用程序正常工作。

2 个答案:

答案 0 :(得分:1)

flatMap可能不会从接收项目的同一个线程中发出,因此您必须通过flatMap运算符后面的观察来确保在所需的线程上接收到事件:

detailView.observeRefresh
        .observeOn(Schedulers.io())
        .map { _ -> detailModel.forecastCity }
        .flatMap { city ->
            detailModel.getForecast(city.id, FORECAST_COUNT)
                    .map { response -> 
                        DetailUiModel.stateSuccess(response.list,
                            detailModel.forecastCity) 
                    }
                    .onErrorReturn { t -> DetailUiModel.stateError(t.message) }
        }
        .startWith(DetailUiModel.stateLoading)       // <---------------------------
        .observeOn(AndroidSchedulers.mainThread())   // <---------------------------
        .subscribe { this.handleResponse(it) }

不再需要内部observeOn,此外,建议您在startWith之前移出observeOn以确保初始状态信号也到达在observeRefresh开始之前纠正线程。

答案 1 :(得分:0)

您应该在observeOn(AndroidSchedulers.mainThread())之前添加.subscribe { this.handleResponse(it) 这是完整的代码:

private val observeRefresh = detailView.observeRefresh
        .observeOn(Schedulers.io())
        .map { _ -> detailModel.forecastCity }
        .flatMap { city ->
            detailModel.getForecast(city.id, FORECAST_COUNT)
                    .map { response -> DetailUiModel.stateSuccess(response.list, detailModel.forecastCity) }
                    .onErrorReturn { t -> DetailUiModel.stateError(t.message) }
                    .observeOn(AndroidSchedulers.mainThread())
                    .startWith(DetailUiModel.stateLoading)
        }
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe { this.handleResponse(it) }