Szukaj…


Wprowadzenie

Moduł ładujący jest dobrym wyborem, aby zapobiec wyciekom pamięci, jeśli chcesz ładować dane w tle, gdy wywoływana jest metoda oncreate. Na przykład, gdy wykonujemy Asynctask metodą oncreate i obracamy ekran, aby działanie zostało odtworzone, co ponownie wykona kolejne AsyncTask, więc prawdopodobnie dwa Asyntask działają równolegle, a nie jak moduł ładujący, który będzie kontynuował proces w tle, który wykonaliśmy wcześniej.

Parametry

Klasa Opis
LoaderManager Klasa abstrakcyjna powiązana z działaniem lub fragmentem do zarządzania jedną lub większą liczbą instancji modułu ładującego.
LoaderManager.LoaderCallbacks Interfejs zwrotny dla klienta do interakcji z LoaderManager.
Ładowarka Klasa abstrakcyjna, która wykonuje asynchroniczne ładowanie danych.
AsyncTaskLoader Moduł ładujący streszczenie, który udostępnia zadanie AsyncTask .
CursorLoader Podklasa AsyncTaskLoader, która wysyła zapytanie do ContentResolver i zwraca kursor.

Uwagi

Programy ładujące wprowadzone w systemie Android 3.0 ułatwiają asynchroniczne ładowanie danych w działaniu lub fragmencie. Ładowarki mają następujące cechy:

  • Są dostępne dla każdego działania i fragmentu .
  • Zapewniają asynchroniczne ładowanie danych.
  • Monitorują źródło swoich danych i dostarczają nowe wyniki, gdy zawartość się zmienia.
  • Automatycznie łączą się ponownie z kursorem ostatniego programu ładującego, gdy są odtwarzane po zmianie konfiguracji. Dlatego nie muszą ponownie sprawdzać swoich danych.

Kiedy nie należy używać modułów ładujących

Nie powinieneś używać modułów ładujących, jeśli potrzebujesz zadań w tle do wykonania. Android niszczy programy ładujące wraz z działaniami / fragmentami, do których należą. Jeśli chcesz wykonać niektóre zadania, które muszą być uruchomione do zakończenia, nie używaj modułów ładujących. Zamiast tego powinieneś korzystać z usług tego typu.

Podstawowy AsyncTaskLoader

AsyncTaskLoader jest abstrakcyjną Loader , który zapewnia AsyncTask do pracy.

Oto podstawowe wdrożenie:

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();
    }
}

Zazwyczaj Loader jest inicjowany w ramach działania w onCreate() sposobu, lub wewnątrz fragmentu w onActivityCreated() . Zwykle także aktywność lub fragment implementuje interfejs 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) {
    }
}

W tym przykładzie, gdy moduł ładujący zostanie ukończony, pojawi się toast z wynikiem.

AsyncTaskLoader z pamięcią podręczną

Dobrą praktyką jest buforowanie załadowanych wyników, aby uniknąć wielokrotnego ładowania tych samych danych.
Aby unieważnić pamięć podręczną, należy onContentChanged() . Jeśli moduł ładujący został już uruchomiony, zostanie forceLoad() , w przeciwnym razie (jeśli moduł ładujący jest w stanie zatrzymania) moduł ładujący będzie w stanie zrozumieć zmianę treści za pomocą opcji takeContentChanged() .

Uwaga: onContentChanged() musi zostać wywołany z głównego wątku procesu.

Javadocs mówi o takeContentChanged ():

Weź aktualną flagę wskazującą, czy zawartość modułu ładującego zmieniła się podczas zatrzymania. Jeśli tak, zwracana jest prawda, a flaga usuwana.

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
    }
}

Ponowne ładowanie

Aby unieważnić stare dane i zrestartować istniejący moduł ładujący, możesz użyć metody restartLoader() :

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

Przekaż parametry za pomocą pakietu

Możesz przekazać parametry według pakietu:

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

Uzyskaj wartość w 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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow