2015-10-30 3 views
0

Во-первых, позвольте мне описать мой случай: я получаю список категорий, которые заполняют RecyclerView. Каждый View в этом списке является своего рода виджетом, и наиболее распространенным является другой список (горизонтальный RecyclerView) с некоторыми новостями (также анализируемыми от JSON).LoaderManager запускает все Погрузчики одновременно

Я сохраняю все в ContentProvider и SQLiteDatabase (с помощником), который содержит две таблицы - для категорий и новостей (каждый из них имеет ключ категории). Поэтому я использую Loader для каждого виджета для загрузки данных из базы данных или, если они отсутствуют, я загружаю правильные данные и вставляю их в db. А затем загрузчик автоматически обновляет список, доставляя новый курсор.

Сразу же на экране могут отображаться два (или более) горизонтальных списка с новостями. Каждый из этих списков регистрации собственного Loader как здесь:

loaderManager.initLoader(getWidgetCategory().getCategoryID(), null, getLoader()); 

под getLoader(); мы же Loader (для виджетов с новостями), как показано ниже:

private class NewsLoader implements LoaderManager.LoaderCallbacks<Cursor> { 

    @Override 
    public Loader<Cursor> onCreateLoader(final int id, final Bundle args) { 
     return new CursorLoader(getContext(), 
       CustomContract.News.CONTENT_URI, 
       CustomContract.News.PROJECTION_ALL, 
       CustomContract.News.KEY_CATEGORY_ID+"=?", 
       new String[]{String.valueOf(getWidgetCategory().getCategoryID())}, 
       CustomContract.News.ORDER_BY_DEFAULT 
     ); 
    } 

    @Override 
    public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) { 
     if (data.getCount()>=15) { 
      swapCursor(data); 
      displayContent(); 
     } 
    } 

    @Override 
    public void onLoaderReset(final Loader<Cursor> loader) { 
     swapCursor(null); 
    } 
} 

, и проблема: когда я загрузить и вставить к новостям базы данных только из одной категории все Loader s увольняют обновляющие списки, и это очень плохо для производительности ... Например - есть два горизонтальных списка с новостями на экране, мы прокручиваем бит вниз и еще один (третий) приближается. У него нет новостей, поэтому фоновая задача загружает их и вставляет в db, а затем LoaderManager запускает Loader для третьего виджета. НО не только ... Также Loaders, прикрепленный к двум спискам выше, запускает обновление собственных списков.

Я предполагаю, что есть проблема с тем же CONTENT_URI, может быть, другие параметры в CursorLoader конструктора. Единственное изменение там (для каждого виджета горизонтального списка новостей) - это статья WHERE с различным идентификатором категории, и все Loader s получают контент из той же таблицы db. Как я могу уволить только один Loader для виджета, который загружал/вставлял новости? Обратите внимание, что идентификатор зарегистрированного загрузчика и выбор WHERE ...

Как я уже писал, могут быть разные типы виджетов (а также списки, но не новости), которые заполняются из других таблиц и их Loader s не стреляют с новостями Loader s. Я предполагаю, что если я получу список категорий с только текстовыми виджетами (также общая таблица db), загрузка текста для одного из виджетов приведет к потере всех «Loader» и перерисовки других виджетов.

редактировать:

В других, коротких словах: в моем обычае ContentProvider я перекрываться query метод, который содержит строку:

@Override 
public Cursor query(
     final Uri uri, 
     final String[] projection, 
     final String selection, 
     final String[] selectionArgs, 
     String sortOrder 
) { 
    //selection, etc. 
    //newly created cursor from selection above 
    cursor.setNotificationUri(getContext().getContentResolver(), uri); 
    return cursor; 
} 

и это уведомляющее все наблюдение Loader с с прошедшим uri. У меня мало списков (неважно, что это RecyclerView s), которые потребляют данные из одного URI, но передают пользовательский параметр выбора для каждого CursorLoader. Но URI является общим для всех, поэтому все загрузчики уведомляются, и я хочу уведомить только об этом, который активировал активность базы данных. Я хочу уведомить только один Loader с известным идентификатором, который также передается методу query внутри selectionArgs. Да, я знаю, что это может быть невозможно внутри query, но, возможно, другим способом?Для уведомления Loader S не только их URI

+0

Пожалуйста, разместите код, создающий 'CursorAdapter'. Используете ли вы параметр flags для регистрации ContentObserver? –

+0

Игнорировать предыдущий комментарий, см. Мой ответ. –

+0

Я думаю, что @alexlockwood должен взвесить на этом. –

ответ

1

URI является общим для всех, так что все загрузчики извещен об этом и я хочу, чтобы уведомить только этот, который обстреливал деятельность базы данных.

Самое простое решение заключается в создании шаблона URI, где URI отличается для каждой категории, поэтому при вызове Cursor.setNoficationUri() каждый курсор (и в конечном счете, каждый загрузчик) будет получать только ContentChanged уведомления для данных она связана с.

Там нет никакого способа, чтобы выключить ContentObserver на CursorLoader, так что если вы абсолютно положительно не может иметь разные идентификаторы URI, то единственное, что я могу предложить, чтобы написать Loader<Cursor> подкласс, который знает, когда для регистрации и отмены регистрации его наблюдателя на курсоре.

(Отредактировано из более раннего ответа)

+0

bullet one: метод initLoader получает идентификатор категории для каждый «Loader», поэтому они разные и уникальные. bullet two: где добавить эту логику? когда я получаю новый курсор в 'onLoadFinished', старый уже закрыт, поэтому я _have_, чтобы заменить это в моем адаптере, когда старый список' Cursor' сработает. Кроме того, провайдер выполняет определенную работу, поэтому даже если старый «Курсор» остается открытым (и я управляю свопинг по собственному), приложение все еще делает ненужную работу с выбором данных для всех «Loader's», в то время как мне нужно только одно. см. мое редактирование с более точным (и коротким) описанием – snachmsm

+0

этого ответа для меня достаточно, я собираюсь пересмотреть некоторые предположения проекта, чтобы они соответствовали поведению 'Loader' ... спасибо – snachmsm