2010-12-13 24 views
7

J'ai ceci:Comment rafraîchir un TextView lors d'une boucle dans Android?

public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 


    TextView debugView = (TextView)findViewById(R.id.debugView); 

    for(int i=0;i<100;i++) { 
     try { 
      Thread.sleep(100); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     debugView.setText(Integer.toString(i)); 
    } 

} 

j'attendre de mettre à jour le texte vue à chaque fois dans la boucle, donc je recevrais: 1, 2, 3, ... 99

lieu l'application ne fait rien pendant 10 secondes et sort ensuite: 99

Je suppose que j'ai besoin de TextView pour actualiser pendant la boucle. Je suis nouveau au développement d'Android. Quelqu'un peut-il me dire si c'est la meilleure façon d'y parvenir?

Mon objectif final est de pouvoir traiter des échantillons audio pour construire un accordeur de guitare. J'essaie simplement de vérifier visuellement que l'application répond à l'audio externe et je veux mettre à jour un TextView pour le démontrer. S'il vous plaît aviser s'il y a une meilleure façon de le faire.

+2

Rien ne s'affiche jusqu'au retour onCreate. – Falmarri

Répondre

6

Votre problème est que vous exécutez votre boucle dans onCreate(). Cela se produit sur le thread de l'interface utilisateur avant que votre activité ne s'affiche.

Jetez un oeil à la Activity lifecycle dans Android. Il montre onCreate n'est qu'une des étapes de la création de l'activité. Ce que vous voulez faire est d'exécuter la boucle sur un thread d'arrière-plan et de poster la notification pour mettre à jour le TextView sur le thread UI en utilisant runOnUiThread. La réponse de Christian montre comment faire cela. Cependant, vu que votre objectif final est de mettre à jour le TextView en fonction d'une entrée de l'utilisateur (audio dans votre cas), vous n'aurez pas à sauter à travers toutes ces boucles pour le faire fonctionner. La seule chose importante est que vous postez vos appels pour mettre à jour l'interface utilisateur sur le thread d'interface utilisateur, sinon vous obtiendrez des exceptions.

+0

Out ofcréer le même problème. –

8

Vous feriez mieux d'utiliser une minuterie:

new Timer().schedule(new TimerTask() { 

     @Override 
     public void run() { 
      runOnUiThread(new Runnable() { 
       public void run() { 
        debugView.setText("something"); 
       } 
      }); 
     } 
    }, 0, 100); 

Notez que j'utilise runOnUiThread puisque vous ne pouvez pas modifier une vue d'un autre thread qui est pas le principal.

+0

Pour mon cas d'utilisation réel, je dois être dans une boucle car je tire des échantillons audio. Je peux déjà afficher la sortie en utilisant Log.i(). Je suis à la recherche d'un moyen simple d'afficher cette information sur l'appareil Android. Peu m'importe le type d'interface nécessaire ou même si je dois dessiner quelque chose en utilisant l'une des interfaces graphiques (si c'est plus rapide que le rendu sur un TextView).J'apprécierais si vous avez des conseils sur la façon de le faire lorsque vous êtes en boucle. Merci. – chaimp

+0

Juste une note, le Thread.sleep (100) était seulement dans le but de tester cela, donc ça ne va pas si vite que ça me manque. Cependant, je ne veux pas qu'il y ait un intervalle de 100 millisecondes. Idéalement, il devrait aller aussi vite que possible. – chaimp

+1

Dans ce cas, utilisez une asyncTask. Il y a beaucoup d'exemples ici dans stackoverflow ou sur Google. – Cristian

22

J'ai eu le même problème et je résolus avec un gestionnaire:

public class myClass extends Activity{ 

private Handler mHandler; 
private TextView text; 
private int i; 

    @Override 
     public void onCreate(Bundle savedInstanceState) { 
      text = (TextView) findViewById(R.id.textView01); 
      i = 0; 
      mHandler = new Handler(); 
      mHandler.post(mUpdate); 

     } 

private Runnable mUpdate = new Runnable() { 
    public void run() { 

     text.setText("My number: " + i); 
     i++; 
     mHandler.postDelayed(this, 1000); 

    } 
};} 

Avec mHandler.post(mUpdate) vous appelez mUpdate qui est un Runnable qui fonctionne dans un autre thread qui peut mettre à jour l'interface utilisateur. À l'intérieur de la méthode run(), au lieu de créer une boucle for, cela poserait le même problème que le vôtre, vous définissez le texte que vous voulez avec une variable auxiliaire, l'incrémentez et appelez mHandler.postDelayed(this,updateTime). A ce moment, la vue est mise à jour, et vous avez votre texte à l'écran, et après le temps que vous avez spécifié (en millisecondes), la mUpdate Runnable va être appelée à nouveau et définit le texte avec le numéro suivant, et ainsi sur.

J'espère que ça aide.

1

Au lieu d'utiliser Handler il est possible de passer directement Runnable à voir avec postDelayed:

public class myClass extends Activity { 

    private TextView text; 
    private int i; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     text = (TextView) findViewById(R.id.textView01); 
     text.postDelayed(mUpdate, 0); 

    } 

    private Runnable mUpdate = new Runnable() { 
     public void run() { 

      text.setText("My number: " + i); 
      i++; 
      text.postDelayed(this, 1000); 

     } 
    }; 
}