"new Thread" does not start a new thread? - android

I want to start a new thread when the line with new Thread executes. I am doing it like this:
new Thread ( new Runnable() {
#Override
public void run() {
.....
}
}).start();
//other code continues here
When the code comes to new thread line it jumps to execute other code. Why?

Well because the new thread almost immediately started running, and the code following the new thread declaration is being executed by the same previous thread.
This is what's happening:
// Main thread running
// Some random code...
new Thread ( new Runnable() {
#Override
public void run() {
// This code will run in another thread. Usually as soon as start() gets called!
}
}).start();
// This code is still being executed by the main thread.
Other than attaching debugger, an easy way to check whether the thread really started running is to put a Log statement inside run()

Simple: because exactly what you want to happen happens!
You create a new thread with new(), and because you call start() immediately on that object, that job starts doing its work.
And your main thread continues its "main" work. It is like: you clap your friend on his shoulder (to signal him: start running) - and now you are asking: "why is he gone?"
That is all there is to this!

Related

Check update periodically using postdelayed

In my app (as long as it is open) I want to sync my data with my server.
My strategy is the following :
//create the handler on which we will use postdelayed
Handler handler = new Handler();
//create the first runnable.
//Will this run on UI thread at this stage ? as it is being called from the handler ?
Runnable runnable1 = new Runnable()
{
public void run()
{
Thread t = new Thread(runnable2);
}
};
//create the second runnable.
//This is for sure being called from a thread, so it will not run on UI thread ? NO ?
Runnable runnable2 = new Runnable()
{
public void run()
{
//connect to internet
//make the check periodical
handler.postdelayed(runnable1, 1000);
}
};
//call the postdelayed.
handler.postdelayed(runnable1, 1000);
In case I want the handler to stop its runnable task once the application is closed. What shall I do incase I have several activities and I do not know where is the user when he/clicks the home button. Should I include a check in all onDestroys() ?
Yes you're second Runnable will be ran on a new thread not the UI thread.
When you do new Handler(); this creates a handle to the current thread, if this code was in onCreate that thread would be the UI thread.
Therefore when you do handler.post it will post onto the UI thread (runnable1) , but when you start runnable2 you are explicitly creating a new thread to run this on.
It might not be the right strategy to create a new thread every 1 second (postDelayed ..1000) perhaps keep a reference to another background thread and post it a message every second to do something new.
To stop your repeated runnables you need to call removeCallbacks(runnable1) in onPause of any Activity (that I assume called postDelayed in onCreate)

Is it safe to assume that a thread created from the main thread is running in the background?

For an app I'm developing, I created a thread from the main thread as follows:
Thread background = new Thread(new Runnable() {
public void run() {
Log.d ("Thread", "Thread has started");
processImage(data, size.width, size.height, camera);
camera.addCallbackBuffer(data);
Log.d ("Thread", "Thread has ended");
}
});
if (!background.isAlive){
background.start();
}
Now, is it safe to assume that this newly created thread is running along with the main thread (in the backgroud)?
Yes, it is safe, after you called start. You can always use the isAlive() method to check whether the thread is executing. Why would you need such an assumption, anyway?
I believe so, as the main thread is always thread id #1 (if you don't believe me, check Thread.currentThread().getId()), and gets initialized before your code does (in your particular case). once that main thread has been created, any subsequent new Thread() should trigger a new instance, which is never the main thread.

What exactly does the post method do?

I've encountered a very weird feature.
When I'm trying to run an animation on the main thread, it does not start.
When I run said animation using
getView().post(new Runnable() {
#Override
public void run() {
getView().startAnimation(a);
}
});
It does start.
I've printed the CurrentThread before starting the animation and both print main.
Obviously, I am missing something here, as both should start the animation on the main thread...
My guess is that as post adds the task to the queue, it starts at a more "correct time", but I would love to know what happens here at more depth.
EDIT:
Let me clear things up - my question is, why starting the animation on post causes it to start, when starting the animation on the main thread does not.
post :post causes the Runnable to be added to the message queue,
Runnable : Represents a command that can be executed. Often used to run code in a different Thread.
run () : Starts executing the active part of the class' code. This method is called when a thread is started that has been created with a class which implements Runnable.
getView().post(new Runnable() {
#Override
public void run() {
getView().startAnimation(a);
}
});
code : getView().startAnimation(a);
in your code,
post causes the Runnable (the code will be run a in different thread) to add the message queue.
So startAnimation will be fired in a new thread when it is fetched from the messageQueue
[EDIT 1]
Why do we use a new thread instead of UI thread (main thread)?
UI Thread :
When application is started, Ui Thread is created automatically
it is in charge of dispatching the events to the appropriate widgets
and this includes the drawing events.
It is also the thread you interact with Android widgets with
For instance, if you touch the a button on screen, the UI thread
dispatches the touch event to the widget which in turn sets its
pressed state and posts an invalidate request to the event queue. The
UI thread dequeues the request and notifies the widget to redraw
itself.
What happens if a user press a button which will do longOperation ?
((Button)findViewById(R.id.Button1)).setOnClickListener(
new OnClickListener() {
#Override
public void onClick(View v) {
final Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap(b);
}
});
The UI freezes. The program may even crash.
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap b = loadImageFromNetwork();
mImageView.setImageBitmap(b);
}
}).start();
}
It breaks the android rule that never update UI directly from worker thread
Android offers several ways to access the UI thread from other threads.
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
Handler
Like below,
View.post(Runnable)
public void onClick(View v) {
new Thread(new Runnable() {
public void run() {
final Bitmap b = loadImageFromNetwork();
mImageView.post(new Runnable() {
public void run() {
mImageView.setImageBitmap(b);
}
});
}
}).start();
}
Handler
final Handler myHandler = new Handler(Looper.getMainLooper());
(new Thread(new Runnable() {
#Override
public void run() {
final Bitmap b = loadImageFromNetwork();
myHandler.post(new Runnable() {
#Override
public void run() {
mImageView.setImageBitmap(b);
}
});
}
})).start();
}
For more info
http://android-developers.blogspot.com/2009/05/painless-threading.html
http://www.aviyehuda.com/blog/2010/12/20/android-multithreading-in-a-ui-environment/
Is this being done on onCreate or onCreateView? If so, the app might not be in a state where the View is attached to the window. A lot of algorithms based on View metrics may not work since things like the View's measurements and position may have not been calculated. Android animations typically require them to run through UI math
View.post actually queues the animation on the View's message loop, so once the view gets attached to the window, it executes the animation instead of having it execute manually.
You are actually running things on the UI thread, but at a different time
Have a look here for a good answer. view.post() is the same as handler.post() pretty much. It goes into the main thread queue and gets executed after the other pending tasks are finished. If you call activity.runOnUiThread() it will be called immediately on the UI thread.
The problem I think could be the life-cycle method where you are calling the post() method. Are you doing it in onCreate()? if so look at what I found in the activity's onResume() documentation:
onResume()
Added in API level 1 void onResume () Called after
onRestoreInstanceState(Bundle), onRestart(), or onPause(), for your
activity to start interacting with the user. This is a good place to
begin animations, open exclusive-access devices (such as the
camera), etc.
https://developer.android.com/reference/android/app/Activity.html#onResume()
So, as Joe Plante said, maybe the view is not ready to start animations at the moment you call post(), so try moving it to onResume().
PD: Actually if you do move the code to onResume() then I think you can remove the post() call since you are already in the ui-thread and the view should be ready to start animations.

Stop thread using return statement

Stop a thread like:
new Thread ( new Runnable() {
public void run(){
if ( condition ) return; // this will stop the thread.
}
}).start();
is correct/safe?
Certainly. The Thread will then finish and can be joined with. The thread would also exit if you threw a RuntimeException or just let the code run off the end of the run() method obviously.
A thread stops when it's run() method returns. It doesn't really matter what logic is used inside run() to decide when or how to return. Your code is perfectly correct and safe.
Yes, it is correct and safe...

Android wait() not working

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.

Categories

Resources