J'ai travaillé avec AsyncTasks sur Android et je suis confronté à un problème. Prenez un exemple simple, une activité avec une asyncTask.Comportement du contexte Android AsyncTask
La tâche en arrière-plan ne fait rien de spectaculaire, elle dort juste pendant 8 secondes.
À la fin de la tâche AsyncTask dans la méthode onPostExecute(), je définis simplement un statut de visibilité de bouton à View.VISIBLE, uniquement pour vérifier mes résultats. Maintenant, cela fonctionne très bien jusqu'à ce que l'utilisateur décide de changer l'orientation de son téléphone pendant que l'AsyncTask fonctionne (dans la fenêtre de veille de 8 secondes). Je comprends le cycle de vie de l'activité Android et je sais que l'activité est détruite et recréée.
C'est là qu'intervient le problème. La tâche asynchrone fait référence à un bouton et contient apparemment une référence au contexte qui a démarré la tâche asynchrone en premier lieu.
Je m'attendais à ce que cet ancien contexte (depuis que l'utilisateur a provoqué un changement d'orientation) soit devenu nul et la tâche asynchrone à lancer un NPE pour la référence au bouton qu'il essaie de rendre visible. Au lieu de cela, aucun NPE n'est levé, le AsyncTask pense que la référence du bouton n'est pas nulle, le définit comme visible. Le résultat? Rien ne se passe sur l'écran!
Mise à jour: Je me suis attaqué à cela en gardant un WeakReference
à l'activité et de commutation quand un changement de configuration se produit. C'est lourd.
Voici le code:
public class Main extends Activity {
private Button mButton = null;
private Button mTestButton = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mButton = (Button) findViewById(R.id.btnStart);
mButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
new taskDoSomething().execute(0l);
}
});
mTestButton = (Button) findViewById(R.id.btnTest);
}
private class TaskDoSomething extends AsyncTask<Long, Integer, Integer>
{
@Override
protected Integer doInBackground(Long... params) {
Log.i("LOGGER", "Starting...");
try {
Thread.sleep(8000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return 0;
}
@Override
protected void onPostExecute(Integer result) {
Log.i("LOGGER", "...Done");
mTestButton.setVisibility(View.VISIBLE);
}
}
}
Essayez d'exécuter et pendant que le AsyncTask travaille changer votre orientation des téléphones.
un peu trompeur d'écrire "garder une référence faible à l'activité" et de ne pas le faire dans le code. Pire encore, plus loin vous dites "et basculer quand un changement de configuration se produit" ce qui ne veut vraiment rien dire ... Changer de quoi? – Ewoks