Android - CursorLoader и SQLite без провайдера контента

52

Я знаю, что это было обсуждено, но я хотел спросить о текущем состоянии дел. Нужно ли создавать ContentProvider для использования CursorLoader в связи с базой данных sqlite?

Я нашел

Использование CursorLoader без ContentProvider

Выглядит точно, на что я надеялся, пока комментирует Emmby

  • Пользователи должны знать об одном ограничении, которое заключается в том, что у него нет механизма для обновления при изменениях данных (как предполагается, должны выполняться Loaders)

Так упоминается другое решение

https://github.com/commonsguy/cwac-loaderex

опять же указывается некоторый недостаток

  • Однако, чтобы использовать автоматический повторный запрос, вам необходимо использовать тот же загрузчик для пользовательского интерфейса, а также для обновлений, ограничивая его удобство использования для фоновых служб.

Конечно, при использовании LoaderManager мы хотим получить все преимущества, для которых он был введен. Поэтому мой вопрос заключается в том, есть ли способ использовать LoaderManager в связи с базой данных sqlite без необходимости реализации поставщика контента, но при этом есть все преимущества.

Спасибо

Теги:
android-contentprovider
android-loadermanager

2 ответа

69
Лучший ответ

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

Недавно я много изучал этот вопрос, и я могу с уверенностью сказать вам, что API Android в настоящее время не предоставляет средства для этого только с помощью raw SQLiteDatabase (он предоставляет только ContentResolver#notifyChange() и Cursor#setNotificationUri(), которые используются для уведомления всех Cursor, зарегистрированных под определенным уведомлением Uri).

Тем не менее, ваши варианты прямо сейчас:

  • Внедрение самого наблюдателя, способного получать уведомления от SQLiteDatabase при изменении содержимого и каким-то образом разрешать эти уведомления для всех существующих Loader в вашем приложении. Я написал довольно обширное сообщение в блоге о том, как реализовать Loader, который может пригодиться, если вы хотите принять по этой проблеме. Или...

  • Используйте библиотеку Mark Murphy LoaderEx и делайте изменения базы данных только с помощью операций AsyncTask, которые предоставляет его библиотека. Обратите внимание, что причина, по которой его задачи обновляют Loader, состоит в том, что они вызывают onContentChanged на Loader сразу после выполнения вставки/обновления/удаления, эффективно сообщая Loader, что содержимое изменилось, и что оно должно обновите его данные.

  • Просто используйте ContentProvider с CursorLoader, и вы можете использовать метод ContentResolver#notifyChange() для уведомления CursorLoader о том, что произошло изменение содержимого.

Я пытаюсь найти лучшее решение, и я буду сообщать в будущем, если я когда-либо его найду/внедрю, но сейчас это нужно будет сделать.

  • 0
    Отлично, спасибо за этот подробный ответ. Принимая это, я просто чувствую, что должен реализовать поставщика контента, даже если это кажется излишним для любой небольшой базы данных, которую я мог бы вывести на дисплей. Хммм ...
  • 1
    @dorjeduck Да, обычно я тоже так делаю. Я действительно хочу найти способ найти способ сделать это, хотя ... Я еще не закончил с этим :)
Показать ещё 10 комментариев
2

Вот мое решение, в моем onCreateLoader

{
Uri u = Uri.parse("content://what_string_you_want");
return new CursorLoader(this, yourURI, projection, null, null, null) {
    private final ForceLoadContentObserver mObserver = new ForceLoadContentObserver();

    @Override
    public Cursor loadInBackground() {
        Cursor c = YOUR_DATABASE.doYourQuery(...);
        if (c != null) {
          // Ensure the cursor window is filled
           c.getCount();
           c.registerContentObserver(mObserver);
        }

        c.setNotificationUri(getContext().getContentResolver(), getUri());
        return c;
    }
};
}

После кода, который изменит БД, добавьте

 getContentResolver().notifyChange(
            Uri.parse("content://same_with_first_string"), null);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню