Android
Ładowarka
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);
...
}