Поиск…


Вступление

Loader - хороший выбор для предотвращения утечки памяти, если вы хотите загрузить данные в фоновом режиме при вызове метода oncreate. Например, когда мы выполняем Asynctask в методе oncreate, и мы поворачиваем экран так, чтобы активность заново воссоздала, что снова запустит еще одну AsyncTask, так что, вероятно, две параллельные Asyntask работают параллельно, а не как загрузчик, которые будут продолжать фоновый процесс, который мы выполнили раньше.

параметры

Учебный класс Описание
LoaderManager Абстрактный класс, связанный с Activity или Fragment для управления одним или несколькими экземплярами Loader.
LoaderManager.LoaderCallbacks Интерфейс обратного вызова для взаимодействия клиента с LoaderManager.
погрузчик Абстрактный класс, который выполняет асинхронную загрузку данных.
AsyncTaskLoader Абстрактный загрузчик, который предоставляет AsyncTask для выполнения работы.
CursorLoader Подкласс AsyncTaskLoader, который запрашивает ContentResolver и возвращает курсор.

замечания

Представленные в Android 3.0 загрузчики упрощают асинхронную загрузку данных в виде активности или фрагмента. Погрузчики имеют следующие характеристики:

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

Когда не использовать Loaders

Вы не должны использовать Loaders, если вам нужны фоновые задачи для завершения. Android уничтожает Loaders вместе с действиями / фрагментами, к которым они принадлежат. Если вы хотите выполнить некоторые задачи, которые должны выполняться до завершения, не используйте Loaders. Вместо этого вы должны использовать сервисы для такого рода вещей.

Основной AsyncTaskLoader

AsyncTaskLoader - абстрактный Loader который предоставляет AsyncTask для выполнения этой работы.

Вот некоторые основные реализации:

final class BasicLoader extends AsyncTaskLoader<String> {

    public BasicLoader(Context context) {
        super(context);
    }

    @Override
    public String loadInBackground() {
        // Some work, e.g. load something from internet
        return "OK";
    }

    @Override
    public void deliverResult(String data) {
        if (isStarted()) {
            // Deliver result if loader is currently started
            super.deliverResult(data);
        }
    }

    @Override
    protected void onStartLoading() {
        // Start loading
        forceLoad();
    }

    @Override
    protected void onStopLoading() {
        cancelLoad();
    }

    @Override
    protected void onReset() {
        super.onReset();

        // Ensure the loader is stopped
        onStopLoading();
    }
}

Обычно Loader инициализируется в onCreate() активности или внутри onActivityCreated() . Также обычно активность или фрагмент реализует интерфейс LoaderManager.LoaderCallbacks :

public class MainActivity extends Activity implements LoaderManager.LoaderCallbacks<String> {

    // Unique id for loader
    private static final int LDR_BASIC_ID = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Initialize loader; Some data can be passed as second param instead of Bundle.Empty
        getLoaderManager().initLoader(LDR_BASIC_ID, Bundle.EMPTY, this);
    }

    @Override
    public Loader<String> onCreateLoader(int id, Bundle args) {
        return new BasicLoader(this);
    }

    @Override
    public void onLoadFinished(Loader<String> loader, String data) {
        Toast.makeText(this, data, Toast.LENGTH_LONG).show();
    }

    @Override
    public void onLoaderReset(Loader<String> loader) {
    }
}

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

AsyncTaskLoader с кешем

Хорошая практика кэширования загруженного результата, чтобы избежать многократной загрузки одних и тех же данных.
Чтобы onContentChanged() недействительность кеша onContentChanged() необходимо вызвать. Если загрузчик уже запущен, forceLoad() , в противном случае (если загрузчик в состоянии остановки) загрузчик сможет понять изменение содержимого с takeContentChanged() проверки takeContentChanged() .

Примечание: onContentChanged() необходимо вызвать из основного потока процесса.

Javadocs говорит о takeContentChanged ():

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

public abstract class BaseLoader<T> extends AsyncTaskLoader<T> {

    // Cached result saved here
    private final AtomicReference<T> cache = new AtomicReference<>();

    public BaseLoader(@NonNull final Context context) {
        super(context);
    }

    @Override
    public final void deliverResult(final T data) {
        if (!isReset()) {
            // Save loaded result
            cache.set(data);
            if (isStarted()) {
                super.deliverResult(data);
            }
        }
    }

    @Override
    protected final void onStartLoading() {            
        // Register observers
        registerObserver();

        final T cached = cache.get();    
        // Start new loading if content changed in background
        // or if we never loaded any data
        if (takeContentChanged() || cached == null) {
            forceLoad();
        } else {
            deliverResult(cached);
        }
    }

    @Override
    public final void onStopLoading() {
        cancelLoad();
    }

    @Override
    protected final void onReset() {
        super.onReset();
        onStopLoading();
        // Clear cache and remove observers
        cache.set(null);
        unregisterObserver();
    }

    /* virtual */
    protected void registerObserver() {
        // Register observers here, call onContentChanged() to invalidate cache
    }

    /* virtual */
    protected void unregisterObserver() {
        // Remove observers
    }
}

перезарядка

Чтобы аннулировать старые данные и перезапустить существующий загрузчик, вы можете использовать restartLoader() :

private void reload() {
    getLoaderManager().reastartLoader(LOADER_ID, Bundle.EMPTY, this);
}

Передача параметров с помощью Bundle

Вы можете передавать параметры через Bundle:

Bundle myBundle = new Bundle();
myBundle.putString(MY_KEY, myValue);

Получите значение в onCreateLoader:

@Override
public Loader<String> onCreateLoader(int id, final Bundle args) {
    final String myParam = args.getString(MY_KEY);
    ...
}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow