Reputation: 987
I have an Android app that after pressing a button starts a function (outside onCreate()). This function changes a global String variable 5 times using a for loop. I want to see every variable shown on the screen (i.e. in a TextView). I understood I have to use a Runnable and a Handler, but..
in MainActivity (extends Activity) / onCreate():
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
handler.post(timedTask);
Start();
}
});
Start() runs, but nothing went on the screen until it had finished.
In MainActivity (extends Activity):
private Runnable timedTask = new Runnable()
{
@Override
public void run()
{
textView1 = (TextView) findViewById(R.id.textView1);
textView1.append(globalMessage);
handler.postDelayed(this, 100);
}};
in MainActivity (extends Activity) / Start():
for(int j = 0; j < 5; j++)
{
...
globalMessage = message[j];
...
}
Upvotes: 2
Views: 1126
Reputation: 987
I got it! The trick is putting all the code from the method/function to the Runnable, then everything is working fine and every text is updating on the spot. So this code:
private Runnable timedTask = new Runnable()
{
@Override
public void run()
{
textView1 = (TextView) findViewById(R.id.textView1);
textView1.append(globalMessage);
handler.postDelayed(this, 100);
}};
becomes:
private Runnable timedTask = new Runnable()
{
@Override
public void run()
{
textView1 = (TextView) findViewById(R.id.textView1);
for(int j = 0; j < 5; j++)
{
...
globalMessage = message[j];
textView1.setText(globalMessage);
...
}
}
};
There are some things I changed though:
Thanks to Tala I changed handler.post(timedTask);
with Thread thread1 = new Thread(timedTask1);
and then thread1.start();
or simply with one line (new Thread(timedTask)).start();
I had some issues with some exceptions:
android.view.ViewRoot$ CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
This accured with textView1.setText(globalMessage);
and textView1.append(globalMessage);
and surely more methods of that type and which are not in onCreate(). If you want to use them out of onCreate then read this answer which suggests replacing that line with:
runOnUiThread(new Runnable() {
@Override
public void run()
{
button1.append(globalMessage);
}
});
Another exception you should look out for is java.lang. NullPointerException which means you should initialise some variables in the current method/runnable/scope
If someone has questions: feel free to comment here!
Upvotes: 0
Reputation: 8928
First of all, you're accessing variable from different threads. You should declare it as volatile
.
So you want your timedTask
to display 5 values of globalMessage?
Make sure to synchronized timedTask with your loop so that after every modification timedTask executes.
for(int j = 0; j < 5; j++)
{
...
globalMessage = message[j];
...// wait sometime here or make sure it is a long operation that is enough for synchronization
}
EDIT
Your handler.post
might not be starting runnable immediately. You can start your runnable yourself:
(new Thread(timedTask)).start(); // instead of handler.post
Or do it the easiest way: just update text in your for loop in the same thread.
Upvotes: 2