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();
}
Related
i want the AsyncTask to wait till it finishes. so i wrote the below code and i used .get() method as follows and as shown below in the code
mATDisableBT = new ATDisableBT();
but at run time the .get() doesnt force ATDisableBT to wait, becuase in the logcat i receive mixed order of messages issued from ATDisableBT and ATEnableBT
which means .get() on ATDisableBT did not force it to wait
how to force the AsyncTask to wait
code:
//preparatory step 1
if (this.mBTAdapter.isEnabled()) {
mATDisableBT = new ATDisableBT();
try {
mATDisableBT.execute().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
//enable BT.
this.mATEnableBT = new ATEnableBT();
this.mATEnableBT.execute();
You can do this way:
doInBackground of AsyncTask
#Override
protected Void doInBackground(String... params) {
Log.i("doInBackground", "1");
synchronized (this) {
try {
mAsyncTask.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Log.i("doInBackground", "2");
return null;
}
Outside this function from where you have to nstrong textotify AsyncTask to release from wait state:
new CountDownTimer(2000, 2000) {
#Override
public void onTick(long l) {
}
#Override
public void onFinish() {
synchronized (mAsyncTask) {
mAsyncTask.notify();
}
}
}.start();
Here I have notified AsyncTask by CountDownTimer after 2 seconds.
Hope this will help you.
You should execute AsyncTask on UI thread, so using get() - which will block it makes no sense - it might get you ANR error.
If you are on HONEYCOMB and up, then AsyncTasks are executed on single executor thread, serially - so your mATEnableBT should get executed after mATDisableBT. For more see here:
http://developer.android.com/reference/android/os/AsyncTask.html#execute(Params...)
You might also switch from AsyncTask to Executors. AsyncTask is implemented using executors. By creating single threaded executor you make sure tasks will get executed serially:
ExecutorService executor = Executors.newSingleThreadExecutor();
//...
executor.submit(new Runnable() {
#Override
public void run() {
// your mATDisableBT code
}
});
executor.submit(new Runnable() {
#Override
public void run() {
// your mATEnableBT code
}
});
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);
}
});
I am trying to show a ProgressDialog for five seconds on user interface to block the UI so that my locationClient can get connected and after five seconds.
I am dismissing the dialog box.But the dialog box is not displaying at all and mobile screen goes black for 3-4 seconds.Is it happening because I am running this code On UiThread?. If yes is their any other approach i can follow to stop for 5 seconds and then execute the pending code.
My code for the thread is following:
public void startConnecting(final boolean isSearchWarnings) {
mProgressDialog = ProgressDialog.show(this, "Please wait","Long operation starts...", true);
MainActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
for (int i = 0; i <= 5; i++) {
try {
if (mLocationClient.isConnected()) {
break;
} else {
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
mProgressDialog.dismiss();
if (isSearchWarnings) {
new getWarnings().execute(false);
} else {
new getWarnings().execute(true);
}
}
});
}
You have this
MainActivity.this.runOnUiThread(new Runnable()
And then
Thread.sleep(1000);
You are calling sleep on the ui thread. This blocks the ui thread which you should not do. You will get ANR.
http://developer.android.com/training/articles/perf-anr.html
If you want to cause a delay use handler
give a delay of few seconds without using threads
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();
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