I'm trying to make a while loop that will make a number count up. However, when the app runs, it just crashes. Here's the code I used:
Thread Timer = new Thread(){
public void run(){
try{
int logoTimer = 0;
while(logoTimer != 5000){
sleep(100);
logoTimer = logoTimer + 1;
button.setText(logoTimer);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
finish();
}
}
};
Timer.start();
Am I doing something wrong? Do I need to add something in the .xml file? Thanks in advance.
it does crash for two reasons
you are touching the UI from a thread that is not the UI Thread
you are calling setText(int), which looks up for a string inside string.xml. If it does not exits, the ResourceNotFoundException will be thrown.
Edit: as G.T. pointed out you can use button.setText(logoTimer+""); to avoid the exception at point 2
You need to run the setText for the button on the UI thread!
MainActivity.this.runOnUiThread(new Runnable() {
public void run() {
button.setText(logoTimer);
}
});
Related
Suppose that I have 10 text views in my layout. I want to change their background one by one with a small delay between each operation. Here's a sample code:
public void test(){
for (int i=0 ; i < 10 ; i++){
myTextViews[i].setBackgroundResource(R.color.red);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
}
}
The problem is that during the time of running this function main thread blocks and backgrounds don't change. They change all together when the program finishes running the function. What should I do if I want the user to see each background is changed at the correct time and then next one...?
When you call Thread.sleep(), the thread you are actually blocking is the UI thread, which is why you're seeing a hang-up. What you need to do is start up another Thread to handle the sleeps, or delays, that you want, and then utilize the runOnUiThread method
Try this:
public void test() {
new Thread(new Runnable() {
public void run() {
for(int i = 0; i < 10; i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//anything related to the UI must be done
//on the UI thread, not this thread we just created
runOnUiThread(new Runnable() {
public void run() {
myTextViews[i].setBackgroundResource(R.color.red);
}
});
}
}
}).start();
}
So, I'm searching on net for a while and now I'm confused... do I need to explicitly end thread after code is executed or thread does it automatically?
Code:
Runnable waitForInput = new Runnable() {
public void run() {
while (!inputOK) {
try {
Thread.sleep(100);
} catch (Exception e) {}
}
if (!ret_val.equals("")) {
port = ret_val;
}
inputOK = false;
ret_val = "";
}
};
Thread inputW = new Thread(waitForInput);
inputW.start();
The Thread ends when the method run ends. Since you have while loop you have to force explicitly the exit condition
Can I use a thread for increment a counter and shows it in a frame of Android activity.
Public class MainActivity extendsActivity {
TextView counter;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
counter = (TextView) findViewById(R.id.TV_counter);
Thread t = new Thread() {
public void run() {
runOnUiThread(new Runnable() {
public void run() {
for (int i = 0; i < 5; i++) {
try {
counter.setText("" + i);
System.out.println("Value of i= " + i);
sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
};
t.start();
}
}
I wrote this code, but it run properly in console, but the text view displays i=4 in the terminal, I modified the time to sleep(3000) and the problem persists.
First you don't ever want to put sleep in UI Thread that can lead to unresponsive user interface and that is never good. You should use it just to update your graphics. Try replacing your code with this
Thread t = new Thread() {
public void run() {
for (int i = 0; i < 5; i++) {
try {
final int a = i;
runOnUiThread(new Runnable() {
public void run() {
counter.setText("" + a);
}
});
System.out.println("Value of i= " + i);
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
t.start();
You are going to notice that sleep and for loop is outside UIThread and in your first thread, so basically all of your math is done outside and you just display the results.
This is just a correction of your code and suggestion for further thinking
EDIT: And for you to better understand why your code is not working, you set some value on your TextView, and immediately after you set UIThread to sleep, UIThread blocks instead of giving it time to finish updating graphics, after he finish sleep you set new value, and he never got to update previous one so in the end you see just the last one.
Hope this helps and enjoy your work.
you can use a CountDownTimer, and update your UI in the onTick() method ( this method is executed on the UI Thread):
int i=0;
CountDownTimer timer = new CountDownTimer(5000,1000) {
#Override
public void onTick(long millisUntilFinished) {
// this method will be executed every second ( 1000 ms : the second parameter in the CountDownTimer constructor)
i++;
txt.setText(i);
}
#Override
public void onFinish() {
// TODO Auto-generated method stub
}
};
timer.start();
Progressbar will not show when I try to access it from a thread nor update the progress. I would prefer to just have a progress spinner be displayed until the network activity is complete, and this network activity is just to post some text data to the server.This is the code I have so far, any help is appreciated thanks,
Thread th = new Thread(){
public void run() {
try {
sleep(5000);
while(cnt < 5000){
activty.this.runOnUiThread(new Runnable(){
public void run()
{
ProgressBar pd = (ProgressBar)findViewById(R.id.progressBar1);
pd.setVisibility(0);
pd.setMax(100);
pd.setProgress(cnt);
cnt += 100;
}
});
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
int cnt = 100;
};
th.start();
`
This is exactly the case where you would want to use AsyncTask, which processes data in a separate thread and contains methods publishProgress and onProgressUpdate to update your UI on the UI thread.
The Processes and Threads Guide has an example of how to implement an AsyncTask as well.
How create a button which pause the thread which is inside the loop and another button which
resumes.
Runnable myRun = new Runnable(){
public void run(){
for(int j =0 ;j<=words.length;j++){
synchronized(this){
try {
wait(sleepTime);
bt.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}});
bt2.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
notify();
}
});
} catch (InterruptedException e) {
e.printStackTrace();
} }
runOnUiThread(new Runnable(){
public void run(){
try {
et.setText(words[i]);
i++;
} catch (Exception e) {
e.printStackTrace();
}
}});
}}};
doing some stuff say words.lenght=1000 times
then suppose user want to take break in between
click pause button with id = bt this button pauses thread until and user
clicks resume with id= bt1
Below is a hint , i think you can use for your problem. Its copied from the link i pasted at end.
A wait can be "woken up" by another process calling notify on the monitor which is being waited on whereas a sleep cannot. Also a wait (and notify) must happen in a block synchronized on the monitor object whereas sleep does not:
Object mon = ...;
synchronized (mon) {
mon.wait();
}
At this point the currently executing thread waits and releases the monitor. Another thread may do
synchronized (mon) { mon.notify(); }(On the same mon object) and the first thread (assuming it is the only thread waiting on the monitor) will wake up.
Check Difference between wait() and sleep()
You do it like this:
How to indefinitely pause a thread in Java and later resume it?
Only you call the suspend() and other methods from your buttons' OnClickListeners