2014-06-17 11 views
5

Questo è qualcosa che ho avuto problemi di recente. A volte, dopo aver chiuso l'app utilizzando il pulsante Home e averlo lasciato pigramente in background per un po ', ottengo il puntatore nullo per getActivity(). Quindi mi chiedo se sto impostando il compito asincrono e gli ascoltatori sbagliati o forse il problema risiede altrove. La mia procedura generale è la seguente:Frammenti, AsyncTask e Listeners

public class MyAsyncTask extends AsyncTask<Void, Void, List<SomeObject>>{ 

    private Context ctx; 
    private AsyncListener listener; 

    public MyAsyncTask(Context ctx){ 
    //set Context, etc 
    } 

... 
    onPostExecute(List<SomeObject> result){ 
     super.onPostExecute(result); 
     if(result!=null){ 
      listener.onAvailable(result); 
     } else { 
      listener.onUnavailable(); 
     } 
    } 

    public interface AsyncListener{ 
     void onAvailable(List<SomeObject> result); 
     void onUnavailable(); 
    } 

    public void setAsyncListener(AsyncListener listener){ 
     this.listener = listener; 
    } 
} 

Frammento:

public class MyFragment extends Fragment implements AsyncListener { 

    private AsyncTask task; 
    private List<SomeObject> data; 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     return inflater.inflate(R.layout.fragment_messages, container, false); 
    } 

    @Override 
    public void onActivityCreated(Bundle savedInstanceState) { 
     // TODO Auto-generated method stub 
     super.onActivityCreated(savedInstanceState); 

     setViews(); 
     if(data == null) { 
      task = new AsyncTask(getActivity()); 
      task.setAsyncListener(this); 
      task.execute(); 
     } else { 
      setData(); 
     } 
    } 

    private void setData(){ 
     someListView.setAdapter(new SomeAdapter(getActivity(), data)); 
    } 

    @Override 
    public void onAvailable(List<SomeObject> result){ 
     this.data = result; 
     setData(); 
    } 

    @Override 
    public void onUnavailable(List<SomeObject> result){ 
     //Create toast or alert dialog, etc 
    } 

} 

Come potete vedere, io uso gli ascoltatori di inviare il risultato di AsyncTask al mio frammento. Il problema è che a volte ricevo un puntatore nullo su getActivity() quando si imposta l'adattatore. Questo accade solo se esco dall'applicazione, lo faccio stare sullo sfondo per un lungo periodo di tempo e poi lo apro. Forse l'ascoltatore viene attivato prima che Frammento sia collegato? Forse ho bisogno di impostare la mia logica in un modo diverso?

risposta

1

Il problema sta in questo pezzo di codice

private void setData(){ 
    someListView.setAdapter(new SomeAdapter(getActivity(), data)); 
} 

Quando si chiude l'attività si può morire in background. Quando termina Asynctask e la funzione SetData viene chiamata dal listener, ottiene null per getActivity() poiché è stata distrutta dal sistema operativo. Controllare getActivity() per null prima di impostare l'adattatore.

+0

Posso provarlo e probabilmente interromperà l'arresto della app, ma ho pensato che forse avrei dovuto impostare i miei ascoltatori in un diverso ciclo di vita del frammento e non in onActivityCreated()? –

+0

È molto probabile che l'ascoltatore sia registrato correttamente poiché trova l'attività quando lo si crea. È solo quando in un tempo indeterministico in futuro l'attività asincrona completa e non trova l'attività che si aspettava di scoprire che si verifica questo errore. Quindi penso che sia qualcosa che è associato alla natura dello stile di operazione asincrono piuttosto che a qualsiasi altra cosa. – Vishal