Aller au contenu

Problème pour mettre a jour du texte depuis un Timer


Sylvain-a

Recommended Posts

Salut à tous,

Ca fait un moment que je ne suis pas venu sur le forum, mais la j'ai grand besoin de votre aide :).

Donc, je conçois une app qui utilise un timer.

Comme c'est un minuteur, je dois mettre a jour le texte d'un TextView disponible dans l'activity concernée.

Seulement, lorsque je tente de faire une mise à jour "indirectement", ça m'indique que le Thread n'est pas le bon.

Comme des lignes d'exemple valent mieux qu'un long discours :


public class MonActivity extends Activity{
 private TextView txt=null;

 public void onCreate(Bundle instance){
 /*Blabla*/
    Timer t=new Timer();
    t.shedule(new MyTimerTask(this), 0, 1000);  // on lance le timer, qui a une période de 1s
   TextView txt=findViewById(monId);
 }

 public void update(){
	 txt.setText("Mon temps");
 }
}

public class MyTimerTask{
   private MonActivity a=null;

   public MyTimerTask(MonActivity a){
    this.a=a;
   }

   public void run(){
       a.update();
   }
}

Donc, je récapitule ce qu'il est censé se passer :

-Je démarre mon Activity qui démarre le Timer -> je passe mon Activity en argument du TimerTask

-Chaque seconde, la fonction update de MonActivity est appelée et met a jour le texte

J'ai essayé de passer le Thread en argument, mais je trouve pas de moyen de l'utiliser.

Je vous remercie par avance pour votre aide.

Cordialement.

PS : j'ai cherché sur le forum & google & faq java & autres, mais n'ai pas vraiment trouvé ce que je cherchais.

Lien vers le commentaire
Partager sur d’autres sites

Le problème, c'est que le Timer tourne dans son propre thread, et essaie de mettre à jour l'UI. Et sous Android, il est interdit de mettre à jour l'UI depuis un autre thread que le principal

Pour résoudre ton problème, tu peux utiliser runOnUiThread, qui te permettra d'exécuter un traitement dans le thread principal depuis un autre thread

Change le corps de la méthode run de ta MyTimerTask

public void run() {
 a.runOnUiThread(new Runnable() {
   public void run() {
  a.update();
   }
 });
}

  • Like 1
Lien vers le commentaire
Partager sur d’autres sites

Merci, ça fonctionne en effet, j'avais aperçu cette méthode lors de mes recherches mais je me demandais si il y avait plus "souple". (En réalité, "monActivity" peut être une activity ou un service donc j'avais créé une interface, et le runOnUiThread est alors indisponible).

En attendant de trouver j'ai tout de même implémenté la méthode que tu m'as proposé :)

Encore merci :)

Si quelqu'un a d'autres propositions je vous remercie d'avance :).

Lien vers le commentaire
Partager sur d’autres sites

Si le traitement à effectuer par le Timer est porté par un Service, tu n'auras pas ce problème d'être obligé de passer par le thread de l'UI, vu que dans un Service, tu n'as pas d'IHM. Dans ce cas, cela devrait fonctionner sans runOnUiThread (hors problématique éventuelle de synchronisation d'accès aux données portées par le Service)

Lien vers le commentaire
Partager sur d’autres sites

Re salut à tous,

Je réécris sur ce topic pour pas trop polluer le forum.

Je tente en vain depuis 3 jours de mettre en place une solution à mon problème, sans résultats.

Donc voici le souci :

Mon activity (la même que précédemment) lance un service. Le service lance un timer.

Ce que je cherche à faire c'est récupérer la valeur actuelle du timer via une méthode (jusque la pas de soucis).

Le problème, c'est que je veux le faire à des instants précis (en gros, à chaque fois que le timer effectue une action).

Je pourrai bien entendu simplement appeler une méthode de mon activity, seulement le service peut aussi être exécuté en tache de fond (donc Lorsque l'activity n'est pas a l'écran). Dans ce cas la, l'activity n'est plus mise à jour jusqu'a ce qu'elle soit résumée.

Seulement je ne trouve pas comment envoyer des informations depuis mon service vers mon activity (Un peu dans la même idée que les évènements).

J'ai regardé du côté de bind et de ServiceConnection... mais sans trouver ce que je cherche.

Avez vous une idée?

Encore merci :).

Modifié par Sylvain-a
Lien vers le commentaire
Partager sur d’autres sites

Utilise le mécanisme des BroadcastReceiver

Il te faut définir un message, qui sera privé à ton application, qui sera envoyé par ton Service (ou plus exactement par le Timer de ton Service) via un sendBroadcast, message qui sera reçu par un BroadcastReceiver, ce dernier n'étant pas déclaré dans le AndroidManifest, mais instancié et enregistré uniquement lorsque ton Activity est affichée; tu recevras donc ton message dans ton Activity, et sera alors capable de la mettre à jour

Lien vers le commentaire
Partager sur d’autres sites

Voici un exemple schématique de solution :)

class MonActivity extends Activity{

   public void onCreate(Bundle instance){
       /*blabla*/

       MonReceiver= receiver=new MonReceiver();

       registerReceiver(receiver, new IntentFilter("monaction"));

   }

}

class MonReceiver(){

   public void onReceive(Context c, Intent i){
       /*blabla*/
   }

}

class MonService(){

   public void update(){
       Intent i=new Intent();
       i.setAction("monaction")
       sendBroadcast(i);
   }
}

Lien vers le commentaire
Partager sur d’autres sites

Ne pas oublier de désenregistrer (méthode unregisterReceiver) le BroadcastReceiver lorsque l'Activity n'est plus active, sinon tu vas avoir des surprises (ton Service envoie un broadcast alors que l'Activity n'est plus présente, le Receiver, toujours enregistré le reçoit et essaie de mettre à jour l'IHM de l'Activity, et badaboum, ça plante ;) )

Je serai toi, j'enregistrerai plutôt le receiver dans le onResume de l'Activity, et le désenregistrerai dans le onPause, le Receiver ne sera actif que lorsque l'Activity a le focus

Lien vers le commentaire
Partager sur d’autres sites

Merci, en réalité c'est ce que j'ai fait, je n'ai juste pas détaillé dans l'exemple.

J'enregistre bien dans le onResume et desenregistre dans le onPause. Je tue le service lorsque l'activité est stoppée.

Sinon, une autre question :

Comment accéder aux fichiers xml depuis un service?

Par exemple, j'aimerai la valeur de app_name dans strings (Donc R.string.app_name).

Seulement, ça a l'air inaccessible depuis le service (avec eclipse en tout cas :()

Y'a t'il un moyen?

Modifié par Sylvain-a
Lien vers le commentaire
Partager sur d’autres sites

Tu veux faire quoi ? Récupérer la valeur de la chaine de caractères identifiée par R.string.app_name ?

Rien de plus simple

String s = getString(R.string.app_name);

depuis un Service ou une Activity (getString est une méthode de la classe Context dont héritent Activity et Service)

Lien vers le commentaire
Partager sur d’autres sites

Rejoignez la conversation

Vous pouvez poster maintenant et vous enregistrez plus tard. Si vous avez un compte, connectez-vous maintenant pour poster.

Invité
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

×
×
  • Créer...