IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Discussion :

Threads (AsyncTask) et rotations d'écran


Sujet :

Android

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Avril 2005
    Messages
    156
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 156
    Par défaut Threads (AsyncTask) et rotations d'écran
    Bonjour à tous,

    Je débute sous Android, et voici la situation : mon activité principale est une TabActivity dans laquelle chaque onglet démarre une nouvelle ListActivity. J'ai besoin au lancement d'une ListActivity d'envoyer une requête HTTP. Voulant faire propre, j'ai utilisé une AsyncTask pour afficher une barre de progression dans l'UI-thread et effectuer la requête dans un autre thread (toutes les ListActivity ont la même structure de code) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    public class FilesActivity extends ListActivity {
     
    	private ArrayList<String> mFiles;
    	private FileAdapter mAdapter;
    	private ProgressDialog mDialog;
     
        @Override
        public void onCreate(Bundle savedInstanceState) {
     
            super.onCreate(savedInstanceState);
     
            setContentView(R.layout.files_list);
     
            mFiles = new ArrayList<String>();
            mDialog = new ProgressDialog(this);
            mDialog.setMessage(getResources().getString(R.string.loading));
            mDialog.setCancelable(false);
     
            new LoadingTask().execute();
     
            mAdapter = new FileAdapter(this, mFiles);
            setListAdapter(mAdapter);
     
        }
     
        private class LoadingTask extends AsyncTask<Void, Void, String> {
     
    		@Override
    		protected void onPreExecute() {
    			mDialog.show();
    		}
     
    		@Override
    		protected String doInBackground(Void... params) {
     
    			String errMsg = null;
     
    	                // [...] Requête HTTP censée remplir mFiles
    			mFiles.add("test");
     
    			return errMsg;
     
    		}
     
    		@Override
    		protected void onPostExecute(String errMsg) {
     
    			if (mDialog.isShowing()) {
    				mDialog.dismiss();
    			}
     
    			if (errMsg == null) {
    				mAdapter.notifyDataSetInvalidated();
    			} else {
    				new AlertDialog.Builder(FilesActivity.this)
    		        			   .setMessage(errMsg)
    		        			   .setPositiveButton(R.string.ok, null)
    		        			   .show();
    			}
     
    		}
     
        }
     
    }
    Le problème, c'est que lors d'un changement d'orientation de l'écran, l'appli plante. On m'a dit d'ajouter le code suivant dans onPause :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
        @Override
        protected void onPause() {
     
        	if (mDialog.isShowing()) {
    			mDialog.dismiss();
    		}
     
        	super.onPause();
     
        }
    Avec ceci, lorsque je teste la ListActivity en tant qu'activité principale, je n'ai plus de problème.

    D'une part, est-ce que quelqu'un pourrait m'expliquer d'où venait le problème ?! Sachant que lors du changement d'orientation de l'écran la barre de progression n'est plus affichée, donc le code ajouté ne devrait pas servir !

    D'autre part, lorsque j'utilise les ListActivity comme activités lancées par la TabActivity (onglets), le problème survient à nouveau après quelques rotations d'écran...Il semblerait que le problème soit dû à l'utilisation d'un autre thread que l'UI-thread (AsyncTask), mais avant d'effectuer la rotation d'écran, j'attends que la barre de chargement disparaisse, donc logiquement le thread ne devrait plus exister, si ? Quelqu'un a-t-il une solution à ce problème ?

    Merci !

  2. #2
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Salut.
    J'ai regardé vite fait ton code.
    Citation Envoyé par j0o0 Voir le message
    D'une part, est-ce que quelqu'un pourrait m'expliquer d'où venait le problème ?
    Normalement on évite d'utiliser les asyncTask dans une activity. Car justement ils peuvent être detruit n'importe quand. Comme une rotation
    Il faut plutôt un service.

    Deuxième problème c'est que tu ne doit pas accéder à des instances de ton activity dans doInBackground. Car cela produit des accès concurrent.
    mFiles.add doit donc être fait dans onProgressUpdate
    http://developer.android.com/referen...pdate(Progress...)

  3. #3
    Membre confirmé
    Inscrit en
    Avril 2005
    Messages
    156
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 156
    Par défaut
    Merci, je prends bonne note de tes conseils. Mais il y a certaines choses que je ne comprends pas : lors de mes tests, j'attendais bien que la barre de chargement disparaisse avant de faire une rotation de l'écran, donc l'asyncTask (et le thread associé) ne devrait plus exister à cet instant...Mais ça n'a pas l'air d'être le cas ! Je ne comprends vraiment pas d'où vient le problème.

    Je vais regarder du côté des services, je pensais que c'était un peu "too much" pour effectuer une simple requête HTTP, mais apparemment c'est la seule solution viable pour faire les choses proprement.

  4. #4
    yan
    yan est déconnecté
    Rédacteur
    Avatar de yan
    Homme Profil pro
    Ingénieur expert
    Inscrit en
    Mars 2004
    Messages
    10 035
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Ille et Vilaine (Bretagne)

    Informations professionnelles :
    Activité : Ingénieur expert
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2004
    Messages : 10 035
    Par défaut
    Citation Envoyé par j0o0 Voir le message
    Mais ça n'a pas l'air d'être le cas ! Je ne comprends vraiment pas d'où vient le problème.
    Difficile de dire comme cela. Je pencherais pour un problème d’accès concurrent ou d'appel de fonction GUI dans un thread.
    Avec le message d’erreur on y verrai peut être plus claire.

  5. #5
    Membre confirmé
    Inscrit en
    Avril 2005
    Messages
    156
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 156
    Par défaut
    En fait je viens de comprendre : lors d'un changement d'orientation, comme prevu les activites sont detruites puis recrees. Or dans ce cas, si j'etais en train de visualiser l'onglet 1 par exemple, l'activite correspondant a l'onglet 0 (affichee par defaut dans la TabActivity) ET l'activite 1 vont etre redemarrees...

    Voici le code de la TabActivity (qui n'est rien d'autre que le code donne dans la doc android) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    public class Main extends TabActivity {
     
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
     
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
     
            Resources res = getResources(); // Resource object to get Drawables
            TabHost tabHost = getTabHost(); // The activity TabHost
            TabHost.TabSpec spec;           // Reusable TabSpec for each tab
            Intent intent;                  // Reusable Intent for each tab
     
            // Create an Intent to launch an Activity for the tab (to be reused)
            intent = new Intent().setClass(this, FilesActivity.class);
            // Initialize a TabSpec for each tab and add it to the TabHost
            spec = tabHost.newTabSpec("files")
            			  .setIndicator("Fichiers", res.getDrawable(R.drawable.ic_tab_files))
                          .setContent(intent);
            tabHost.addTab(spec);
     
            // Do the same for the other tabs
            intent = new Intent().setClass(this, WebsitesActivity.class);
            spec = tabHost.newTabSpec("websites")
            			  .setIndicator("Sites web", res.getDrawable(R.drawable.ic_tab_websites))
                          .setContent(intent);
            tabHost.addTab(spec);
     
            intent = new Intent().setClass(this, StreamsActivity.class);
            spec = tabHost.newTabSpec("streams")
            			  .setIndicator("Streams", res.getDrawable(R.drawable.ic_tab_streams))
                          .setContent(intent);
            tabHost.addTab(spec);
     
            //tabHost.setCurrentTab(0);
     
        }
     
    }
    Comment faire pour empecher l'activite par defaut (onglet 0) de redemarrer ?

    PS : desole pour les accents, clavier QWERTY...

  6. #6
    Expert confirmé

    Avatar de Feanorin
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    4 589
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 4 589
    Par défaut
    Salut ,

    pour régler ton problème , tu peux utiliser setCurrentTab ou setDefaultTab en sauvegardant la valeur de ton index current dans le bundle lors de la destruction de ton activity (via un getCurrentTab ou tu peux aussi passer par onContentChange de la tabactivity et sauvegarder ton index au fur et à mesure) permettant de mettre à jour ton tabhost au démarrage de ton activity .

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Rotation d'écran - boutons qui ne réagissent plus
    Par kesakoo dans le forum Composants graphiques
    Réponses: 0
    Dernier message: 24/06/2015, 14h37
  2. Thread, AsyncTask et Handler
    Par Feanorin dans le forum Android
    Réponses: 1
    Dernier message: 23/12/2014, 14h45
  3. Synchronisation 2 thread asynctask
    Par jojo_ol76 dans le forum Android
    Réponses: 2
    Dernier message: 26/10/2011, 17h25
  4. Effectuer une rotation d'écran.
    Par adrien954 dans le forum Windows Forms
    Réponses: 1
    Dernier message: 08/10/2009, 09h41
  5. Thread et affichage direct3D plein écran
    Par Harry_polin dans le forum DirectX
    Réponses: 8
    Dernier message: 13/03/2003, 22h22

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo