Подтвердить что ты не робот

Android - CursorLoader & SQLite без Content Provider

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

Я нашел

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

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

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

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

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

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

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

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

Спасибо

4b9b3361

Ответ 1

В двух реализациях, которые вы упомянули в своем посте, предлагаются все преимущества 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 о том, что произошло изменение содержимого.

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

Ответ 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);