Sök…


Introduktion

Loader är ett bra val för att förhindra läckage av minnet om du vill ladda data i bakgrunden när oncreate-metoden kallas. Till exempel när vi kör Asynctask i oncreate-metod och vi roterar skärmen så att aktiviteten kommer att återskapa vilket kommer att köra ytterligare en AsyncTask igen, så antagligen kommer två Asyntask att köras parallellt tillsammans snarare än som loader som kommer att fortsätta bakgrundsprocessen vi körde tidigare.

parametrar

Klass Beskrivning
LoaderManager En abstrakt klass associerad med en aktivitet eller ett fragment för att hantera en eller flera Loader-instanser.
LoaderManager.LoaderCallbacks Ett återuppringningsgränssnitt för en klient att interagera med LoaderManager.
Lastare En abstrakt klass som utför asynkron belastning av data.
AsyncTaskLoader Abstrakt lastare som ger en AsyncTask för att utföra arbetet.
CursorLoader En underklass av AsyncTaskLoader som frågar ContentResolver och returnerar en markör.

Anmärkningar

Laddare introducerade i Android 3.0 och gör det enkelt att asynkront ladda data i en aktivitet eller ett fragment. Lastare har dessa egenskaper:

  • De är tillgängliga för alla aktiviteter och fragment .
  • De tillhandahåller asynkron laddning av data.
  • De övervakar källan till sina data och levererar nya resultat när innehållet ändras.
  • De ansluter automatiskt till den senaste lastarens markör när de återskapas efter en konfigurationsändring. Därför behöver de inte fråga igenom sina uppgifter.

När man inte ska använda lastare

Du bör inte använda Loaders om du behöver bakgrundsuppgifterna för att slutföra. Android förstör lastare tillsammans med de aktiviteter / fragment de tillhör. Om du vill utföra några uppgifter som måste köras tills de är klar, använd inte Lastare. Du bör använda tjänster för den här typen av saker istället.

Grundläggande AsyncTaskLoader

AsyncTaskLoader är en abstrakt Loader som tillhandahåller en AsyncTask att utföra arbetet.

Här en del grundläggande implementering:

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

Vanligtvis initialiseras Loader inom aktivitetens onCreate() eller inom fragmentets onActivityCreated() . Oftast implementerar också aktivitet eller fragment LoaderManager.LoaderCallbacks gränssnittet:

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

I det här exemplet visas rostat bröd med resultat när lastaren är klar.

AsyncTaskLoader med cache

Det är bra att cache-laddat resultat för att undvika att flera data laddas flera gånger.
För att onContentChanged() cache onContentChanged() kallas. Om loader redan har startats kommer forceLoad() att forceLoad() , annars (om loader i stoppat tillstånd) kommer loader att kunna förstå innehållsändring med takeContentChanged() -kontroll.

Anmärkning: onContentChanged() måste onContentChanged() från processens huvudtråd.

Javadocs säger om takeContentChanged ():

Ta den aktuella flaggan som indikerar om laddarens innehåll har ändrats medan det stoppades. Om det hade gjort, returneras sant och flaggan rensas.

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

omlastning

För att ogiltiga dina gamla data och starta om befintlig lastare kan du använda restartLoader() :

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

Skicka parametrar med hjälp av ett paket

Du kan skicka parametrar efter Bundle:

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

Få värdet i 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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow