Suche…


Einführung

Loader ist eine gute Wahl, um Speicherverluste zu vermeiden, wenn Sie beim Aufruf der oncreate-Methode Daten in den Hintergrund laden möchten. Wenn wir zum Beispiel Asynctask in der Oncreate-Methode ausführen und den Bildschirm so drehen, dass die Aktivität erneut erstellt wird, wird eine weitere AsyncTask erneut ausgeführt, sodass wahrscheinlich zwei Asyntask parallel laufen und nicht wie ein Loader, der den zuvor ausgeführten Hintergrundprozess fortsetzt.

Parameter

Klasse Beschreibung
LoaderManager Eine abstrakte Klasse, die einer Aktivität oder einem Fragment zugeordnet ist, um eine oder mehrere Loader-Instanzen zu verwalten.
LoaderManager.LoaderCallbacks Eine Rückmeldeschnittstelle, über die ein Client mit dem LoaderManager interagieren kann.
Lader Eine abstrakte Klasse, die asynchrones Laden von Daten durchführt.
AsyncTaskLoader Abstraktes Ladeprogramm , das eine AsyncTask für die Arbeit bereitstellt .
CursorLoader Eine Unterklasse von AsyncTaskLoader, die den ContentResolver abfragt und einen Cursor zurückgibt.

Bemerkungen

In Android 3.0 eingeführt, ermöglichen Lader das asynchrone Laden von Daten in einer Aktivität oder einem Fragment. Lader haben folgende Eigenschaften:

  • Sie sind für jede Aktivität und jedes Fragment verfügbar.
  • Sie ermöglichen das asynchrone Laden von Daten.
  • Sie überwachen die Quelle ihrer Daten und liefern neue Ergebnisse, wenn sich der Inhalt ändert.
  • Sie stellen automatisch eine Verbindung zum Cursor des letzten Laders her, wenn sie nach einer Konfigurationsänderung neu erstellt werden. Daher müssen sie ihre Daten nicht erneut abfragen.

Wann sollten Loader nicht verwendet werden

Sie sollten keine Loader verwenden, wenn Sie Hintergrundaufgaben ausführen müssen. Android zerstört Lader zusammen mit den zugehörigen Aktivitäten / Fragmenten. Wenn Sie einige Aufgaben ausführen möchten, die bis zum Abschluss ausgeführt werden müssen, verwenden Sie keine Loader. Sie sollten stattdessen Dienste für diese Art von Sachen verwenden.

Grundlegender AsyncTaskLoader

AsyncTaskLoader ist ein abstrakter Loader , der eine AsyncTask für die Arbeit AsyncTask .

Hier einige grundlegende Implementierungen:

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

Typischerweise wird Loader innerhalb der onCreate() Methode der Aktivität oder innerhalb der onActivityCreated() des Fragments onActivityCreated() . In der Regel implementiert auch activity oder fragment die Schnittstelle 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) {
    }
}

In diesem Beispiel wird nach Abschluss des Laders Toast mit Ergebnis angezeigt.

AsyncTaskLoader mit Cache

Es empfiehlt sich, geladene Ergebnisse zwischenzuspeichern, um das mehrfache Laden derselben Daten zu vermeiden.
Um den Cache ungültig zu machen, sollte onContentChanged() aufgerufen werden. Wenn der Loader bereits gestartet wurde, wird forceLoad() aufgerufen. Andernfalls (wenn der Loader im angehaltenen Zustand ist) kann der Loader die takeContentChanged() mit takeContentChanged() check nachvollziehen.

Anmerkung: onContentChanged() muss vom Haupt-Thread des Prozesses aufgerufen werden.

Javadocs sagt über takeContentChanged ():

Nehmen Sie das aktuelle Flag, um anzuzeigen, ob sich der Inhalt des Laders geändert hat, während er gestoppt wurde. Wenn ja, wird true zurückgegeben und das Flag wird gelöscht.

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

Neuladen

Um Ihre alten Daten zu restartLoader() und den vorhandenen Loader neu zu starten, können Sie die restartLoader() Methode verwenden:

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

Übergeben Sie Parameter mit einem Bundle

Sie können Parameter per Bundle übergeben:

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

Rufen Sie den Wert in onCreateLoader ab:

@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
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow