RxJava2 запрос SQLite

В моем приложении для 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();
            }
        }
    }

вы уверены, что вам нужен универсальный Observable в этом случае? Single тоже можно наблюдать, но он имеет более лаконичный API (см. обновленный ответ)

Droidman 25.01.2019 09:58
0
1
453
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть много способов добиться желаемого. Вы не предоставили много контекста, поэтому я возьму в качестве примера следующее:

  • у вас есть несколько 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 25.01.2019 09:41

@Fivos относительно обработки нулей: RxJava2 больше не допускает нулевых значений, поэтому пустой список - ваш лучший вариант. Если вы не хотите на самом деле возвращать пустой список из самого метода выборки, вы можете добавить следующую строку при подписке: .onErrorReturnItem(ArrayList()). Таким образом, NPE будет перехвачен, а onSuccess будет вызван с пустым списком.

Droidman 18.02.2019 10:42

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