I'd like to do setText() on a TextView and make the activity sleep just after.
Here is the code :
tv.setText("myText");
tv.invalidate(); // Doesn't work
pause(1000); // French for sleep
And my function pause :
public void pause(int seconds)
{
synchronized(this)
{
try {
this.wait(seconds);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
}
The problem is that the TextView doesn't update before sleeping. I tried to call invalidate() on my TextView but it doesn't work.
I have another possible solution : create a new Thread for sleeping the activity, and if the value of my TextView is still the same, reload the Thread, else call my function pause(). But is it possible to get the real value of my TextView in the View ? Because I can get the new text when I do :
tv.setText("myText");
System.out.println(tv.getText());
pause(1000); // French for sleep
Whereas the text doesn't update in the View.
Any idea ?
I would suggest what Jave said.
tv.setText("myText");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Do something
}
}, 3000); //3000 is time in ms.
If you use the UI thread and make it sleep for too long , you will get the application-not-responding dialog . of course , only when the function ends , you will see the new value , so this is not a good solution . you can use handlers if you wish to use only the UI thread.
If you use a different thread , you will need to set the text of the TextView somehow using the UI thread since it's the only one that is allowed to do so (use handler for this) .
Related
I am trying to change the screen of an app during a function is running.
public void StartRecording(View view)
{
start_button.setEnabled(false);
stop_button.setEnabled(true);
recording = true;
while(recording==true)
{
// Here is a code that changes many views on the screen
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
function StartRecording() is called by clicking the start_button in the xml file.
recording is set to false when clicking the stop_button.
The views on the screen should change, wait a second, change again, wait a second and so on.
But what happens is that the function waits until the loop is finished and then shows only the final screen change. What am I doing wrong?
Thanks ahead : )
Edit:
I tried using Handler and it has the same result..
private final Handler mHandler = new Handler(Looper.getMainLooper())
{
public void handleMessage(Message msg)
{
tv.setText((String) msg.obj);
}
};
tv is a textView. Instead of using tv.setText just above the try{} in the code above, I sent a message to mHandler to change the text, and it still changes it only after the whole startRecording function is over.
Now, what am I doing wrong? :/
What am I doing wrong
you are calling sleep wait the UI Thread, that is responsible for drawing your views and handle events. If you want to schedule 10 different redrawing of your views, you can use and Handler and its postDelayed method
I am displaying image on when clicking on a Button using interface but the image ic_launcher.png does not show up on the Button after some time the image_all.png is only shown.
How should I show my first image for some time using sleep and then show image2?
Should I show both the images on the same button but with time delay.
Any help would be appreciated.
try{
button1.setBackgroundResource(R.drawable.ic_launcher);
Thread.sleep(1000);
} catch(Exception e){
}
button1.setBackgroundResource(R.drawable.images_all);
When you use Thread.sleep(1000); you're actually "stopping" the UI thread, because you're calling sleep(1000); on the UI thread. This causes your application to halt completely for 1 second in your case.
So this isn't such a good idea :-)
Instead you should use something like a Handler for instance. A Handler can be called with a specified delay, so that the action will first be performed after the specified delay. And most importantly, the Handler doesn't "block" the UI thread, as the Thread.sleep(1000); does.
So using a Handler your code, could look something like this instead:
button1.setBackgroundResource(R.drawable.ic_launcher);
Handler uiHandler = new Handler();
uiHandler.postDelayed(new Runnable() {
#Override
public void run() {
button1.setBackgroundResource(R.drawable.images_all);
}
}, 1000);
Notice the 1000 in the end of postDelayed() which tells the Handler to post this "message" after 1000 milliseconds instead of immediately.
On a side-note: It's not good practice to "eat" the Exceptions like you do in your try-catch.
You should be able to see the R.drawable.ic_launcher change occur. My thoughts about this are around how you're doing the Thread.sleep(). Android isn't fond of performing blocking tasks (such as Thread.sleep) in the UI Thread. When you call the setBackgroundResource and then sleep, the thread that would update the UI is sleeping and cannot perform the update. This is how I would do it instead:
button1.setBackgroundResource(R.drawable.ic_launcher);
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
button1.setBackgroundResource(R.drawable.images_all);
}
}, 1000);
This question already has an answer here:
Updating UI / runOnUiThread / final variables: How to write lean code that does UI updating when called from another Thread
(1 answer)
Closed 9 years ago.
Good day,
I want to update an image button in my UI from another thread. below is my code that i run in my mains threads onCreate() method.
new Thread(new Runnable() {
public void run() {
ImageButton btn = (ImageButton) findViewById(R.id.connected_icon);
if (netConnection.IsConnected()) {
// Change icon to green
btn.setImageResource(R.drawable.green_small);
} else {
// Change icon to red
btn.setImageResource(R.drawable.red_small);
}
try {
// Sleep for a second before re_checking.
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
No when i run this i gen an error int he LogCat saying i cannot update the UI from annother thread.
I remember reading soem where once that this is the case so that you don't get multiple threads updating the same UI object at once. But how can i achieve this. i am sure there is a work around?
Thanks
You cannot directly acces UI components from the thread.
The correct way to do this is by creating a handler
final Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
}
};
And send messages to UIThread with
Message msg = new Message();
//TODO: add stuff to message
mHandler.sendMessage(msg);
inside your Thread.
This or use an AsyncTask instead and do the updates from inside of pre, post or progressUpdate methods
UI Elements should be updated only from the UI thread. Use an async task to do background word, and modify the UI in onPostExecute, which runs on the UI thread
This is my first question here, so please forgive me if I disobeyed any of the forum rules.
I need my program to wait for 3 seconds and then change the Content View
My code is:
setContentView(R.layout.logout);
new Thread(new Runnable() {
#Override
public void run(){
try {
synchronized(this){
wait(3000);
}
}
catch(InterruptedException ex){
}
}
}).start();
setContentView(R.layout.main);
The program works with no errors, but there is no waiting. When it gets to this part, it just shows the "main" layout without showing the "logout" layout at all.
What is wrong in my approach?
As people noted, don't sleep on or otherwise block the UI thread, but you seem to be aware of this with the new thread you create.
Now for why it doesn't behave as you want:
Right now, you call setContentView(), start a new thread, call setContentView() a second time on the UI thread -- this happens in quick succession with no delay/wait/sleep inbetween. The wait(3000) happens in the new thread you started -- so that new thread starts, waits for 3000ms, then exits. It's an expensive no-op.
You would need to make the second call to setContentView() from inside that new thread's run() method to get the desired effect. Also, you should use sleep() instead of wait() -- wait() is a low-level tool for synchronizing threads while sleep() is the usual "don't continue for X amount of time".
Let me propose a better way:
An arguably nicer and much lighter approch is using Handler.postDelayed() -- this allows you to invoke a Runnable on the UI thread after a delay:
setContentView(R.layout.logout);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
setContentView(R.layout.main);
}
}, 3000);
Edit to reply to your comment:
Define and find the button before the Runnable as a final variable, this way you can access it later from inside the Runnable.
Please note that to reference the this instance of the surrounding class from inside an anonymous inner class (your new Runnable()), you need to prefix it with the class name of the surrounding class (your Activity class):
final View submitButton = findViewById(R.id.submit_button);
setContentView(R.layout.logout);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
setContentView(R.layout.main);
// adapt to your actual Activity class name:
submitButton.setOnClickListener(YourClassName.this);
}
}, 3000);
wait() doesn't wait for a certain amount of time, but rather has the current Thread wait for this to do a notify() for a maximum amount of time. What you are looking for, is Thread.sleep().
And at the moment the only thing that will be waiting, is the additional thread you are spawning, not the activity itself. That's why I'd suggest you look at Handler.postDelayed(), CountDownTimer or AsyncTask. Handling threads is very low-level.
Your code not work to sleep UI thread.To sleep UI thread try this code
new Handler().postDelayed(new Runnable()
{
public void run()
{
setContentView(R.layout.main);
}
}, 3000);
Try using Sleep() instead of Wait()
android.os.SystemClock.sleep(3000)
As far as i can understand the wait is happening in the new thread where as you are calling setContentView(R.layout.main) in the current thread.
Try
setContentView(..)
synchronized(this) {
this.wait(1000);
}
setContentView(..)
Please note sleeping or waiting in the UI thread is not a best practice though.
I can't understand the implementation of a while loop in android.
Whenever I implement a while loop inside the onCreate() bundle, (code shown below)
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
TextView=(TextView)findViewById(R.id.TextView);
while (testByte == 0)
updateAuto();
}
nothing boots up, and the program enters a "hanging" state after a while and I can't understand why. Testbyte is as follows:
byte testByte == 0;
and updateAuto() is supposed to update the code per 1 second and display inside the textView portion. I've been using setText inside updateAuto() as shown below and everything works fine, but once i implement the while loop all i see is a black screen and then an option to force close after a few seconds due to it "not responding".
TextView.setText(updateWords);
I've changed it to a button format (meaning i have to click on the button to update itself for now), but i want it to update itself instead of manually clicking it.
Am i implementing the while loop in a wrong way?
I've also tried calling the while loop in a seperate function but it still gives me the black screen of nothingness.
I've been reading something about a Handler service... what does it do? Can the Handler service update my TextView in a safer or memory efficient way?
Many thanks if anyone would give some pointers on what i should do on this.
Brace yourself. And try to follow closely, this will be invaluable as a dev.
While loops really should only be implemented in a separate Thread. A separate thread is like a second process running in your app. The reason why it force closed is because you ran the loop in the UI thread, making the UI unable to do anything except for going through that loop. You have to place that loop into the second Thread so the UI Thread can be free to run. When threading, you can't update the GUI unless you are in the UI Thread. Here is how it would be done in this case.
First, you create a Runnable, which will contain the code that loops in it's run method. In that Runnable, you will have to make a second Runnable that posts to the UI thread. For example:
TextView myTextView = (TextView) findViewById(R.id.myTextView); //grab your tv
Runnable myRunnable = new Runnable() {
#Override
public void run() {
while (testByte == 0) {
Thread.sleep(1000); // Waits for 1 second (1000 milliseconds)
String updateWords = updateAuto(); // make updateAuto() return a string
myTextView.post(new Runnable() {
#Override
public void run() {
myTextView.setText(updateWords);
});
}
}
};
Next just create your thread using the Runnable and start it.
Thread myThread = new Thread(myRunnable);
myThread.start();
You should now see your app looping with no force closes.
You can create a new Thread for a while loop.
This code will create a new thread to wait for a boolean value to change its state.
private volatile boolean isClickable = false;
new Thread() {
#Override
public void run() {
super.run();
while (!isClickable) {
// boolean is still false, thread is still running
}
// do your stuff here after the loop is finished
}
}.start();