Android
caricatore
Ricerca…
introduzione
Loader è una buona scelta per prevenire perdite di memoria se si desidera caricare i dati in background quando viene chiamato il metodo oncreate. Ad esempio, quando eseguiamo Asynctask nel metodo oncreate e ruotiamo lo schermo in modo da ricreare l'attività che eseguirà di nuovo un altro AsyncTask, quindi probabilmente due Asyntask in esecuzione in parallelo piuttosto che come loader che continuerà il processo in background eseguito in precedenza.
Parametri
Classe | Descrizione |
---|---|
LoaderManager | Una classe astratta associata ad un attività o frammento per la gestione di una o più istanze Loader. |
LoaderManager.LoaderCallbacks | Un'interfaccia di callback per un client per interagire con LoaderManager. |
caricatore | Una classe astratta che esegue il caricamento asincrono dei dati. |
AsyncTaskLoader | Caricatore astratto che fornisce un AsyncTask per eseguire il lavoro. |
CursorLoader | Una sottoclasse di AsyncTaskLoader che interroga ContentResolver e restituisce un Cursore. |
Osservazioni
Introdotto in Android 3.0, i caricatori semplificano il caricamento asincrono dei dati in un'attività o in un frammento. I caricatori hanno queste caratteristiche:
- Sono disponibili per ogni attività e frammento .
- Forniscono il caricamento asincrono dei dati.
- Monitorano la fonte dei loro dati e forniscono nuovi risultati quando il contenuto cambia.
- Si riconnettono automaticamente al cursore dell'ultimo caricatore quando vengono ricreati dopo una modifica della configurazione. Quindi, non hanno bisogno di ri-interrogare i loro dati.
Quando non usare i caricatori
Non è necessario utilizzare Caricatori se è necessario completare le attività in background. Android distrugge i caricatori insieme alle attività / ai frammenti a cui appartengono. Se si desidera eseguire alcune attività, che devono essere eseguite fino al completamento, non utilizzare Caricatori. Dovresti invece usare i servizi per questo genere di cose.AsyncTaskLoader di base
AsyncTaskLoader
è un programma di Loader
astratto che fornisce un AsyncTask
per eseguire il lavoro.
Ecco alcune implementazioni di base:
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();
}
}
In genere Loader
viene inizializzato all'interno del metodo onCreate()
dell'attività o all'interno di onActivityCreated()
del frammento. Inoltre, solitamente l'attività o il frammento implementa LoaderManager.LoaderCallbacks
interfaccia 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 questo esempio, quando il caricatore è completato, verrà mostrato un brindisi con il risultato.
AsyncTaskLoader con cache
È buona norma memorizzare nella cache i risultati caricati per evitare il caricamento multiplo degli stessi dati.
Per invalidare la cache onContentChanged()
dovrebbe essere chiamato. Se il loader è già stato avviato, verrà chiamato forceLoad()
, altrimenti (se il caricatore è in stato di arresto) il caricatore sarà in grado di comprendere la modifica del contenuto con il controllo takeContentChanged()
.
Nota: onContentChanged()
deve essere chiamato dal thread principale del processo.
Javadocs dice di takeContentChanged ():
Prendi il flag corrente per indicare se il contenuto del caricatore è stato modificato mentre era fermo. In tal caso, viene restituito true e la bandiera viene cancellata.
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
}
}
Ricaricamento
Per invalidare i vecchi dati e riavviare il caricatore esistente è possibile utilizzare il metodo restartLoader()
:
private void reload() {
getLoaderManager().reastartLoader(LOADER_ID, Bundle.EMPTY, this);
}
Passa i parametri usando un pacchetto
Puoi passare i parametri per Bundle:
Bundle myBundle = new Bundle();
myBundle.putString(MY_KEY, myValue);
Ottieni il valore in onCreateLoader:
@Override
public Loader<String> onCreateLoader(int id, final Bundle args) {
final String myParam = args.getString(MY_KEY);
...
}