Гораздо более интересный вопрос, чем кажется <3 </p>
Чтобы решить вашу проблему, мы должны взглянуть на код, сгенерированный Room - для следующего:
@Transaction
@Query("DELETE FROM plants WHERE id IN (:listOfId)")
abstract fun deleteThings(listOfId: MutableList<String>): Maybe<Int>
Сгенерированный код:
@Override
public Maybe<Integer> deleteThings(final List<String> listOfId) {
StringBuilder _stringBuilder = StringUtil.newStringBuilder();
_stringBuilder.append("DELETE FROM plants WHERE id IN (");
final int _inputSize = listOfId.size();
StringUtil.appendPlaceholders(_stringBuilder, _inputSize);
_stringBuilder.append(")");
final String _sql = _stringBuilder.toString();
SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
int _argIndex = 1;
for (String _item : listOfId) {
if (_item == null) {
_stmt.bindNull(_argIndex);
} else {
_stmt.bindString(_argIndex, _item);
}
_argIndex ++;
}
return Maybe.fromCallable(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
__db.beginTransaction();
try {
final java.lang.Integer _result = _stmt.executeUpdateDelete();
__db.setTransactionSuccessful();
return _result;
} finally {
__db.endTransaction();
}
}
});
}
Итак, мы видим, что сама операция находится внутри блока Maybe.fromCallable
, который является частью, на которую будет влиять subscribeOn(Schedulers.io())
.Итак, если executeUpdateDelete();
выполняется в фоновом потоке, почему вы получаете исключение?
См. Эту строку:
SupportSQLiteStatement _stmt = __db.compileStatement(_sql);
Если мыпроверьте внутреннюю часть этого метода ....
/**
* Wrapper for {@link SupportSQLiteDatabase#compileStatement(String)}.
*
* @param sql The query to compile.
* @return The compiled query.
*/
public SupportSQLiteStatement compileStatement(@NonNull String sql) {
assertNotMainThread(); // <-- BOOM!
return mOpenHelper.getWritableDatabase().compileStatement(sql);
}
Таким образом, очевидно, что даже при составлении запроса утверждается, что он не находится в главном потоке, поэтому наличие Maybe
не имеет значения;блок вне Maybe.fromCallable
выполняется в текущем потоке независимо от того, что вы делаете.
Это можно решить, выполнив «синхронно исполняемую часть» для выполнения в фоновом потокетоже.
mDisposables.add(
Maybe.defer {
mThingsDao.deleteThings(listOfId)
.subscribeOn(Schedulers.io())
}.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
...
}, {
...
})
)