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 :

ProgressDialog - AsyncTask + Changement d'orientation


Sujet :

Android

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 130
    Par défaut ProgressDialog - AsyncTask + Changement d'orientation
    Bonjour,

    J'ai un gros soucis avec la gestion de l'orientation et l'affichage d'une ProgressDialog pendant un long traitement.
    En effet si je pivote l'orientation pendant que la progress dialog est active, ça me faut planter mon programme...

    Voici mon implementation:
    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
     
    // android:configChanges="keyboardHidden|orientation" dans le manifest
    public class ProgTv extends Activity {
     
    	private LoadProgTvData progData;
    	/** Called when the activity is first created. */
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.main);
     
    		//loadProgTvData();
    	}
     
    	@Override
    	public void onConfigurationChanged(Configuration newConfig) {
    		super.onConfigurationChanged(newConfig);
    		setContentView(R.layout.main);
    	}
     
    	@Override
    	public Object onRetainNonConfigurationInstance() {
    		progData.setActivity(null);
    		return progData;
    	}
     
    	@Override
    	protected void onResume() {
    		super.onResume();
    		loadProgTvData();
    	}
     
    	private void loadProgTvData() {
    		final Object retained = getLastNonConfigurationInstance();
    		if(retained instanceof LoadProgTvData) {
    			progData = (LoadProgTvData) retained;
    			progData.setActivity(this);
    		} else {
    			progData = new LoadProgTvData(this, null);
    		}
    	}
    }
    LoadProgTvData :
    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
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    public class LoadProgTvData {
    	private Activity activity;
    	private static List<ProgTvObj> lst_prog = new ArrayList<ProgTvObj>();
    	private static ProgTvAdapter progTvAdapter = null;
            private Hours progHours;
    	public static enum Hours { BEGINING_EVENING, END_EVENING };
     
    	public LoadProgTvData(Activity activity, Hours h) {
    		this.activity = activity;
                    this.progHours = h;
     
    		if(lst_prog.isEmpty())
    			new ListRefresher().execute();
    		else
    			refreshListView();
    	}
     
    	public void setActivity(Activity activity) {
    		this.activity = activity;
    		if(!lst_prog.isEmpty())
    			refreshListView();
    	}
     
    	/**
             * Set List of ProgTvObj from an XML stream
             */
    	private void setListFromXml() {
    		// SAX Parser
    		try {
    			ProgSaxXml px = new ProgSaxXml(activity.getAssets().open("soir.xml")); // SAX Parser		
    			lst_prog = px.getProgList();
    		} catch (MalformedURLException e) {
    			Log.d("MalformedURLException", "XML Url is malformed", e);
    			throw new RuntimeException(e);
    		} catch (IOException e) {
    			Log.d("IOException", e.toString());
    		}
    	}
     
    	/**
             * Set Adapter of ListView to fill it with ProgTvObj 
             */
    	public void refreshListView() {
    		//Hours progHours = (Hours) getIntent().getSerializableExtra("tabHours"); // Get Hours value or null if not defined
    		if(null != activity) {
    			if(null == progTvAdapter)			
    				progTvAdapter = new ProgTvAdapter(activity);
    			if(null != progHours)
    				progTvAdapter.setListProg(myUtils.filter(lst_prog, progHours));
    			else
    				progTvAdapter.setListProg(lst_prog);
    			ListView lstview_prog = (ListView)activity.findViewById(R.id.lstview_prog);
    			lstview_prog.setAdapter(progTvAdapter);
    			lstview_prog.setOnItemClickListener(progTvAdapter);
    		}
    	}
     
    	class ListRefresher extends AsyncTask<Uri, Void, Void> {
    		private ProgressDialog progressDialog;
    		@Override
    		protected void onPreExecute() {
    			if(!lst_prog.isEmpty()) {
    				this.cancel(true);
    				refreshListView();
    			} 
    			else
    				progressDialog = ProgressDialog.show(activity, null, "Chargement en cours...");
    		}
     
    		@Override
    		protected Void doInBackground(Uri... params) {
    			setListFromXml();
    			return null;
    		}
     
    		@Override
    		protected void onPostExecute(Void result) {
    			progressDialog.dismiss();
    			refreshListView();
    		}
    	}
    }
    Sachant que si je met loadProgTvData(); dans le OnResume c'est parce que mon Activity est un onglet de mon tableau et le faut de changer d'onglet ne rapelle pas OnCreate. Or j'ai besoin que ma liste soit rafraichit à chaque passage.

    Je pense que le problème viens du fait que la ProgressDialog est crée dans un context et le changement d'orientation change le context et donc au moment du dismiss il doit pas savoir quoi faire.

    Si vous pouviez m'aider ça serai vraiment sympa. Car le problème sur le lequel je bloque est quand même une chose que tout le monde doit réaliser dans une appli mobile (telechargement avec message d'attente...).

  2. #2
    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 la gestion de l'orientation tu n'as pas besoin de passer par
    onConfigurationChanged.

    Regarde plutôt du côté de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    	protected Dialog onCreateDialog(int id) {
    http://developer.android.com/guide/t...i/dialogs.html

    Il gère tout seul le dialogue lors d'une rotation .

    Si tu as un souci avec cette procédure fais signe .

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 130
    Par défaut
    J'ai rajouté :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    protected Dialog onCreateDialog(int id) {
    	if(id == 0){
    		ProgressDialog loadingDialog = new ProgressDialog(this);
    		loadingDialog.setMessage("Chargement en cours...");
    		loadingDialog.setIndeterminate(true);
    		loadingDialog.setCancelable(true);
    		return loadingDialog;
    	} 
    	return super.onCreateDialog(id);
    }
    et dans la inner class de LoadProgTvData j'ai modifié :
    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
    class ListRefresher extends AsyncTask<Uri, Void, Void> {
    	//private ProgressDialog progressDialog;
    	@Override
    	protected void onPreExecute() {
    		if(!lst_prog.isEmpty()) {
    			this.cancel(true);
    			refreshListView();
    		} else
    			activity.showDialog(0);
    		/*else
    			progressDialog = ProgressDialog.show(activity, null, "Chargement en cours...");*/
    	}
     
    	@Override
    	protected Void doInBackground(Uri... params) {
    		setListFromXml();
    		return null;
    	}
    	@Override
    	protected void onPostExecute(Void result) {
    		//progressDialog.dismiss();
    		activity.dismissDialog(0);
    		refreshListView();
    	}
    }

    Mais j'obtiens le message d'erreur suivant :

    ERROR/AndroidRuntime(5089): java.lang.NullPointerException
    ERROR/AndroidRuntime(5089): at org.prozero.util.LoadProgTvData$ListRefresher.onPostExecute(LoadProgTvData.java:191)
    ERROR/AndroidRuntime(5089): at org.prozero.util.LoadProgTvData$ListRefresher.onPostExecute(LoadProgTvData.java:1)
    ....


    La ligne 191 est la ligne avec activity.dismissDialog(0); -> toujours le problème du dismiss et crash de l'appli.
    Est ce que mon implementation est bonne ?

  4. #4
    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,

    Garde en mémoire ta progress pour pouvoir interagir directement dessus.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    private ProgressDialog loadingDialog = null;
    protected Dialog onCreateDialog(int id) {
         super.onCreateDialog(id);
         if(id == 0){
    		loadingDialog = new ProgressDialog(this);
    		loadingDialog.setMessage("Chargement en cours...");
    		loadingDialog.setIndeterminate(true);
    		loadingDialog.setCancelable(true);
    		return loadingDialog;
    	} 
    	return null;
    }

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    	@Override
    	protected void onPreExecute() {
    		if(!lst_prog.isEmpty()) {
    			this.cancel(true);
    			refreshListView();
    		} else
    			showDialog(0);
     
    	}


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
     
    	@Override
    	protected void onPostExecute(Void result) {
    		if(loadingDialog != null)
                        loadingDialog.dismiss();
     
    		refreshListView();
    	}

  5. #5
    Jay
    Jay est déconnecté
    Membre expérimenté
    Profil pro
    Inscrit en
    Juin 2002
    Messages
    124
    Détails du profil
    Informations personnelles :
    Localisation : France, Gironde (Aquitaine)

    Informations forums :
    Inscription : Juin 2002
    Messages : 124
    Par défaut
    Bonjour,

    Sinon tu bloques la rotation de ton Activity.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    <activity android:name="TonActivity"
    android:screenOrientation="portrait"></activity>
    Cordialement,

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Juin 2009
    Messages
    130
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2009
    Messages : 130
    Par défaut
    Citation Envoyé par Feanorin Voir le message
    Salut,

    Garde en mémoire ta progress pour pouvoir interagir directement dessus.
    Malheureusement, la AsyncTask (qui fait le showDialog) est dans une classe à part et n'as donc pas accès aux membres de mon Activity (sauf via la valeur de activity passée en param à la classe).

    En revanche j'ai outre passé le problème :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    @Override
    protected void onPostExecute(Void result) {
    	//progressDialog.dismiss();
    	try {
    		activity.dismissDialog(0);
    	} catch(Exception e) {	}
    	refreshListView();
    }
    Le try catch permet de ne pas traiter la NullException (car sinon il la throw au RunTime).
    Plus de message, plus de plantage et en plus ça marche...mais c'est pas forcement la meilleure solution...

    @Jay : oui mais je voudrai pouvoir garder la rotation...


    Ou alors il faudrait que ma classe à part (LoadProgTvData) hérite de Activity
    et que Ma classe principale hérite de la classe à part (LoadProgTvData) ?
    Et redefinir le OnCreate dans la classe principale...
    (car plusieurs Activity implemente ma classe LoadProgTvData actuellement)

  7. #7
    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
    Tu peux aussi faire un Handler sur ta ListRefresher . Ou l'activity en cours se liera avec cet handler pour récupérer les messages envoyés, En fonction du message tu sauras si tu dois afficher ou détruire la progress , de plus cet handler peut te permettre de faire autre chose , comme gérer les messages d'erreur à partir de ton activity .

    Voilà cela reste qu'une idée

Discussions similaires

  1. WebI BO XI changement d'orientation du text
    Par atb dans le forum Webi
    Réponses: 6
    Dernier message: 06/05/2008, 15h42
  2. Changement d'orientation professionnelle
    Par y_a_b dans le forum Emploi
    Réponses: 2
    Dernier message: 23/01/2008, 15h12
  3. [TCPDF] changement d'orientation portrait/paysage
    Par Pixys dans le forum Bibliothèques et frameworks
    Réponses: 8
    Dernier message: 22/12/2007, 21h46
  4. Réponses: 10
    Dernier message: 08/09/2006, 08h41

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