Jump to content

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.

Link to comment
Share on other 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
Link to comment
Share on other 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 :).

Link to comment
Share on other 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)

Link to comment
Share on other 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 :).

Edited by Sylvain-a
Link to comment
Share on other 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

Link to comment
Share on other 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);
   }
}

Link to comment
Share on other 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

Link to comment
Share on other 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?

Edited by Sylvain-a
Link to comment
Share on other 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)

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...