La risposta di Phoenixblade9 è corretta, ma per renderlo completo aggiungerei una cosa.
C'è un ottimo sostituto per AsyncTask - AsyncTaskLoader, o Loaders in generale. Gestisce il suo ciclo di vita in base al contesto da cui è stato chiamato (Attività, Frammento) e implementa un gruppo di ascoltatori per aiutarti a separare la logica di un secondo thread dal thread dell'interfaccia utente. Ed è generalmente immune dal contesto che perde.
E non infastidire il nome: è un vantaggio anche per il salvataggio dei dati.
Come promesso pubblicherò il mio codice per AsyncTaskLoader con più oggetti restituiti. Il caricatore più o meno così:
public class ItemsLoader extends AsyncTaskLoader<HashMap<String, Object>>{
HashMap<String, Object> returned;
ArrayList<SomeItem> items;
Context cxt;
public EventsLoader(Context context) {
super(context);
//here you can initialize your vars and get your context if you need it inside
}
@Override
public HashMap<String, Object> loadInBackground() {
returned = getYourData();
return returned;
}
@Override
public void deliverResult(HashMap<String, Object> returned) {
if (isReset()) {
return;
}
this.returned = returned;
super.deliverResult(returned);
}
@Override
protected void onStartLoading() {
if (returned != null) {
deliverResult(returned);
}
if (takeContentChanged() || returned == null) {
forceLoad();
}
}
@Override
protected void onStopLoading() {
cancelLoad();
}
@Override
protected void onReset() {
super.onReset();
onStopLoading();
returned = null;
}
Nella funzione getYourData()
ottengo sia il codice messaggio del server o qualche altro codice di errore e di un ArrayList<SomeItem>
. Posso uso nel mio Frammento come questo:
public class ItemListFragment extends ListFragment implements LoaderCallbacks<HashMap<String, Object>>{
private LoaderManager lm;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
lm = getLoaderManager();
Bundle args = new Bundle();
args.putInt("someId", someId);
lm.initLoader(0, args, this);
}
@Override
public Loader<HashMap<String, Object>> onCreateLoader(int arg0, Bundle args) {
ItemsLoader loader = new ItemsLoader(getActivity(), args.getInt("someId"));
return loader;
}
@Override
public void onLoadFinished(Loader<HashMap<String, Object>> loader, HashMap<String, Object> data) {
if(data!=null){ if(data.containsKey("items")){
ArrayList<SomeItem> items = (ArrayList<EventItem>)data.get("items");
} else { //error
int error = 0;
if(data.containsKey("error")){
error = (Integer) data.get("error");
}
}
}
@Override
public void onLoaderReset(Loader<HashMap<String, Object>> arg0) {
}
fonte
2012-05-22 20:08:38
Il rischio è, in questo caso se si mantiene il riferimento alla AsyncTask quando il frammento è morto. L'utente potrebbe dire di fare un'azione che apre il frammento dalla pila. In questo caso, di solito non vorresti più che lo stato di Fragment esista. Se si desiderava lo stato di asynctask perché conteneva dati aggiuntivi che si desidera utilizzare, quindi manterrebbe il riferimento al frammento anche se il frammento non dovrebbe più esistere. Credo che sarà distaccato dall'attività da quando ha attraversato il normale ciclo di vita, ma sarebbe comunque "esistito". – DeeV
@DeeV: Sì, è esattamente ciò di cui mi preoccupavo – Matthias
Potresti semplicemente passare a assegnarlo a un WeakReference e annullare AsyncTask se il Frammento diventa nullo? – DeeV