Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to refresh a TextView while looping in Android?

I have this:

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));
    }

}

I would expect it to update the text view each time through the loop so I would get: 1, 2, 3, ... 99

Instead the app does nothing for 10 seconds and then outputs: 99

I am guessing that I need the TextView to refresh during the loop. I am new to Android development. Can somebody please tell me if this is the best way to accomplish this?

My eventually goal is to be able to process audio samples to build a guitar tuner. I am trying to simply verify visually that the app is responding to external audio and I want to update a TextView to demonstrate that. Please advise if there is a better way to do this.

like image 696
chaimp Avatar asked Dec 13 '10 03:12

chaimp


4 Answers

Instead of using Handler it's possible to directly pass Runnable to view with 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);

        }
    };
}
like image 54
shtolik Avatar answered Sep 30 '22 05:09

shtolik


You better use a timer:

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

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

Notice that I'm using runOnUiThread since you can't modify a view from another thread that is not the main one.

like image 33
Cristian Avatar answered Nov 05 '22 03:11

Cristian


I had the same problem and I resolved it with a handler:

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);

    }
};}

With mHandler.post(mUpdate) you call mUpdate that is a Runnable that runs in a different thread that can update the UI. Inside the method run(), instead of creating a for loop, that would have the same problem as yours, you set the text that you want with an auxiliary variable, increment it and call mHandler.postDelayed(this,updateTime). In this moment, the view updates, and you have your text in the screen, and after the time that you have specified (in milliseconds), the Runnable mUpdate is going to be called again and sets the text with the next number, and so on.

I hope it helps.

like image 23
Racker Avatar answered Nov 05 '22 04:11

Racker


Your problem is that you are running your loop in onCreate(). This is happening on the UI thread before your Activity is displayed.

Take a look at the Activity lifecycle in Android. It shows onCreate is just one of the stages in the Activity creation. What you'll want to do is run the loop on a background thread and post the notification to update the TextView onto the UI thread using runOnUiThread. Christian's answer shows how to do this.

However, seeing as your final goal is to update the TextView based on some user input (audio in your case) you won't have to jump through all these loops to make it work. The only important thing is that you post your calls to update the UI on the UI thread, otherwise you'll get exceptions.

like image 7
pheelicks Avatar answered Nov 05 '22 05:11

pheelicks