В моем приложении для Android я хотел бы использовать RxJava2 вместо AsyncTasks для запроса моей локальной базы данных SQLite. Я не хочу использовать оболочки Room или SqlBrite. Так можно ли получить, например, Observable<List<Invoice>> из такого запроса? Если да, приведите пример.
например Я хочу поместить следующий метод в шаблон Observable-Observer, чтобы он возвращал Observable<List<Invoice>>.
private List<Invoice> fetchInvoices() {
Cursor cursor = null;
try {
cursor = getContentResolver().query(JPBContentProvider.CONTENT_URI,
null, null, null, null);
if (cursor != null) {
List<Invoice> list = new ArrayList<>();
while (cursor.moveToNext()) {
list.add(Invoice.from(cursor));
}
return list;
}
} catch (Exception ex) {
return null;
} finally {
if (cursor != null && !cursor.isClosed()) {
cursor.close();
}
}
}
Есть много способов добиться желаемого. Вы не предоставили много контекста, поэтому я возьму в качестве примера следующее:
Invoice, хранящихся в базе данныхListПример для Kotlin, но для Java он будет очень похож.
Итак, вот ваш метод выборки БД:
fun queryInvoices(): List<Invoice>{
val results = arrayListOf<Invoice>()
// your logic to retrieve data from SQLite
return results
}
Предполагая, что вам нужно получить различные типы данных, имеет смысл определить общий метод, который будет выполнять магию Rx. Это в основном однострочный код в Котлине:
fun <T>rxFetchData(func: () -> List<T>): Single<List<T>> = Single.fromCallable(func)
Как это работает: аргумент этого метода — функция, которая не принимает аргументов (в этом примере) и возвращает List некоторого типа. Single.fromCallable откладывает выполнение этой функции до тех пор, пока вы не подпишетесь (проверьте ссылку для получения дополнительной информации).
Использование:
fun fetchInvoices() {
rxFetchData(::queryInvoices)
.subscribeOn(io())
.observeOn(mainThread())
.subscribe(
{ data ->
Log.i("onSuccess", " fetched ${data.size} invoices")
},
{ error ->
error.printStackTrace()
})
}
И вот импорт, который вам понадобится:
import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers.mainThread
import io.reactivex.schedulers.Schedulers.io
ОБНОВИТЬ
Вы можете сделать что-то подобное (Java):
public Single<List<Invoice>> invoices(){
return Single.fromCallable(this::fetchInvoices);
}
Спасибо за ваш немедленный ответ! Я обновил свой вопрос, чтобы быть более описательным.
@Fivos относительно обработки нулей: RxJava2 больше не допускает нулевых значений, поэтому пустой список - ваш лучший вариант. Если вы не хотите на самом деле возвращать пустой список из самого метода выборки, вы можете добавить следующую строку при подписке: .onErrorReturnItem(ArrayList()). Таким образом, NPE будет перехвачен, а onSuccess будет вызван с пустым списком.
вы уверены, что вам нужен универсальный
Observableв этом случае?Singleтоже можно наблюдать, но он имеет более лаконичный API (см. обновленный ответ)