Android - отменить регистрацию ContentObserver, определенного в адаптере

У меня есть серия файлов для загрузки. Они хранятся как записи в контент-провайдере. Каждая запись также содержит процент загруженных файлов.

Одно действие отображает список загрузок, каждый файл представляет собой элемент с ProgressBar, показывающий ход загрузки.

Я обновляю этот индикатор выполнения через ContentObserver. Внутри CursorAdaptor я определяю ContentObserver для каждого элемента и сохраняю его как тег соответствующего представления.

Моя проблема сейчас в том, что я не знаю, когда отменить регистрацию таких ContentObservers. Единственный способ, который я нашел, был в содержании активности onDestroy():

    for (int i = 0; i < mListView.getChildCount(); i++) {
        final View v = mListView.getChildAt(i);
        final ContentObserver obs = (ContentObserver) v.getTag();
        if (obs != null) {
            getContentResolver().unregisterContentObserver(obs);
        }
    }

Это действительно ужасно. Он вводит зависимость между адаптером и родительской активностью. С другой стороны, незарегистрированные ContentObservers могут предотвратить уничтожение активности, вызывая утечку памяти.

Вы видите лучший способ?


person ticofab    schedule 05.06.2013    source источник
comment
Вы должны по крайней мере переместить свой цикл отмены регистрации в onPause() (и, следовательно, зарегистрировать его в onResume()), потому что вы не всегда можете предвидеть, когда будет вызван onDestroy() или система убьет ваше приложение, даже не вызвав его.   -  person ozbek    schedule 13.06.2013
comment
@shoe_rat, это неправда, это зависит от того, в каком методе жизненного цикла вы выполнили регистрацию ContentObserver. Если вы отменяете регистрацию в onPause, пока вы выполняете вызов регистрации в onCreate, он будет бомбить при возврате к этому действию несколько раз (или вам потребуются дополнительные проверки). Кроме того, то, что вы говорите о случае, когда приложение убивает система, не соответствует действительности, так как зарегистрированный ContentObserver будет разрегистрирован системой, если система убьет вас (конечно, иначе вы бы съели ресурсы, будучи убитым все время).   -  person Pepster    schedule 05.07.2013
comment
Не привязывайте состояние к представлениям, представления приходят и уходят. Зарегистрируйте одного наблюдателя, который получает объект, содержащий все данные, обновите эти данные для адаптера, вызов notifyDataSetInvalidated() для адаптера.   -  person S.D.    schedule 13.07.2013
comment
С.Д. правильно, используйте только один ContentObserver и не связывайте представления с информацией о состоянии   -  person Mikel    schedule 02.08.2013


Ответы (1)


Если у вас есть поставщик контента, вместо этого вы можете использовать CursorLoader.

https://developer.android.com/training/load-data-background/setup-loader.html

public class PhotoThumbnailFragment extends FragmentActivity implements
        LoaderManager.LoaderCallbacks<Cursor> {
...
}

/*
* Callback that's invoked when the system has initialized the Loader and
* is ready to start the query. This usually happens when initLoader() is
* called. The loaderID argument contains the ID value passed to the
* initLoader() call.
*/
@Override
public Loader<Cursor> onCreateLoader(int loaderID, Bundle bundle)
{
    /*
     * Takes action based on the ID of the Loader that's being created
     */
    switch (loaderID) {
        case URL_LOADER:
            // Returns a new CursorLoader
            return new CursorLoader(
                        getActivity(),   // Parent activity context
                        mDataUrl,        // Table to query
                        mProjection,     // Projection to return
                        null,            // No selection clause
                        null,            // No selection arguments
                        null             // Default sort order
        );
        default:
            // An invalid id was passed in
            return null;
    }
}

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

person Cory Roy    schedule 15.01.2014