There's something weird happening. I can't show all the code, but situation is like this;
Runnable program = new Runnable() {
#Override
public void run() {
//This code is running
new Handler();
//This code not running
}};
new Thread(program).start();
Log shows nothing. Main thread is working good.
You should always declare Handler in UI thread.You need to provide the Handler with a Looper from some thread.E.g. from main UI thread:
Handler mHandler = new Handler(Looper.getMainLooper());
Handler always runs in the Looper thread context. When you create another thread its context is different from the Looper. Right solution is to declare Handlers always in onCreate(), onStart() and onResume().
Creating a Handler needs a Looper polling on that thread first. By the way, there's usually no need to create a Handler inside non UI threads. Create a Handler outside the runnable. An easier alternative is to use runOnUiThread() method.
Related
I have a class with multiple functions, each function were containing a separate handler to execute a runnable. Recently I realized that we must remove all the callbacks on the onDestroy method to avoid memory leaks, so for that, I declared a class-level handler and used the same handler to post runnable in all the functions.
Now my confusion is, what happens if we use the same instance of Handler for multiple runnable compared to a separate handler instance for each runnable?
No matter how many handlers you have, all those handler will pos their messages to the same queue which is main thread queue by default, unless you attach the handler to different looper objects excplicitly. To illustrate in code:
// This handler will be attached to the main thread's looper,
// hence to its queue implicitly but however this constructor
// is deprecated and is not recommended.
Handler handlerMain = new Handler();
// This handler will be attached to the main thread's looper
// object explicitly and this is the recommended way by Google.
Handler handlerMain = new Handler(Looper.getMainLooper());
// Another handler will be attached to the main thread's looper object.
Handler handlerMain2 = new Handler(Looper.getMainLooper());
// This is a custom handler thread whis has a looper object same as the apllication's main (ui) thread. But this one will be a background thread.
HandlerThread mHandlerThread = new HandlerThread("MyHandlerThread");
mHandlerThread.start();
// Now this handler will post messages to the mHandlerThread's queue.
// Hence you cannot access directly to the UI elements from this thread,
// you must post the ui touching codes to the main thread's queue.
Handler handlerCustom = new Handler(mHandlerThread.getLooper());
You can attach many handlers to a looper, the handlers are not the problem. The problem is the code that they post. You can post a delayed code that will be executed in a future time, and that code touches some UI elements of a fragment or access context of a fragment. The problem comes when the fragment's view and context is destroyed before the posted code has been executed.
I have a Handler, mHandler, tied to the main thread. mHandler resides in a Service. Say I now post a Runnable to mHandler from the main thread like so:
public class SomeService extends Service {
// Handler is created on the main thread
// (and hence it is tied to the main thread)
private Handler mHandler = new Handler();
#Override
public void onDestroy() {
// onDestroy runs on the main thread
// Is the code in this Runnable processed right away?
mHandler.post(new Runnable() {
// (Some code statements that are to be run on the main thread)
...
});
super.onDestroy();
}
}
I know the example is a little silly as the Handler is unnecessary. However, it is a good example for this question.
Now my questions are:
Will the code statements in the Runnable be processed right away as the thread that posts the Runnable is also the thread that is to process the Runnable? Or does it work differently as the Handler internally uses a MessageQueue and hence there might be Runnables posted to the Handler elsewhere (which arrive before my Runnable)?
Moreover, is it possible that the statements will never run as the post(Runnable r) is an async call and hence onDestroy() will finish and the Service will be killed by the system before the Handler gets to run the code.
Thank you in advance.
Since a Service does not imply a separate thread, your runnable will be posted at the end of the main Looper's queue, so yes, there may be messages/runnables scheduled before yours.
Again, since Service does not imply a distinct thread, a call to onDestroy does not mean that the Handler's thread has been terminated. In this example, you are posting to the main looper, and that thread is active until the application process terminates.
Android doc says: "Each Handler instance is associated with a single thread.."
So, if I define the following handler inside onCreate() method:
myHandler= new Handler();
then myHandler will be associated with the main (UI) thread?
I would like to see an example where a handler is "associated" with a worker thread. If you have any, I would appreciate.
Thanks.
There are two questions here.
The answer to the first is "yes". If that line of code is in onCreate, then myHandler is associated with the UI thread
A Handler is cannot be associated with just any thread. It must be associated with a Looper. The very first paragraph of the documentation of the Looper gives an example.
This much is true: If you use the default constructor for Handler, then your Handler object will be associated with the current thread - whatever it is.
However, you will note that the Handler class has several other constructors. If you provide the Looper argument to the Handler constructor, then your handler will be associated with the thread that is associated with the Looper. (Note that Looper detects and holds onto the thread that it is constructed in.)
You can create a Thread with a Looper by instantiating a Looper in the thread's run() method. But Android has already done this for you in the HandlerThread class: HandlerThread class is a subclass of Thread and has a Looper - perhaps a better name for HandlerThread would have been LooperThread. In any case, HandlerThread class also has a method called getLooper(). So, you first create an instance of HandlerThread, and then use its getLooper() as an argument to your Handler constructor:
HandlerThread myLooperThread=new HandlerThread("LooperThread");
myLooperThread.start();
Handler myLooperHandler=new Handler (myLooperThread.getLooper(),
new MyLooperHandlerCallback());
myLooperHandler.sendEmptyMessage(50);
The above snippet can be executed in your UI thread, but will still associate myLooperHandler with the HandlerThread's thread. You can verify this, by logging thread id, as in:
//runs in HandlerThread's thread
public class MyHandlerCallback implements Callback {
#Override
public boolean handleMessage(Message msg) {
Log.i("CALLBACK", "Thread ID:"+android.os.Process.myTid());
Log.i("CALLBACK", "msg.what:"+msg.what);
return true;
}
}
Note that it is best to instantiate threads in retained worker fragments, so that they are accessible across Activity boundaries.
My question Is that What is the difference between Thread and Handler
Q1) What are their effects When they are used in 1) Activity 2) Service
Q2) What is difference between them in context with their life span
I am using following codes for them.
1) ---------------------------
final Handler handler = new Handler();
Runnable runnable = new Runnable()
{
public void run()
{
// do somthing
handler.postDelayed(this, 1000);
}
};
runnable.run();
2) ---------------------------
handler = new Handler()
{
#Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
}
};
new Thread(new Runnable()
{
public void run()
{
while(true)
{
try
{
Thread.sleep(1000);
handler.sendEmptyMessage(0);
} catch (InterruptedException e) {}
}
}
}).start();
Handler:
handler is used to do looper thing.that is to perform same task number of time.
handler can be executed on main thread.
about Handler if its used in service it may get stop if phone state change to sleep.
u can update the UI through handler if it used in activity.
Thread:
Thread is used to things on separate than the main thread of an activity.
thread always runs in background even if phone state changes to sleep mode.
u cant update the UI of as its not running on main thread.it can be done using asynctask not using simple java thread.
Q0) What is the difference between a thread and a handler?
A Thread is the same as it always is in programming. Each thread executes a single call to a method and then terminates. Each thread runs in parallel with every other thread. Threads are in short the way you have more than one thing happening at once.
Passing information between threads is notoriously difficult...
A Handler is Android's way of passing a message from one thread to another. Specifically it allows you to pass a set of instructions as a Runnable into a thread for that thread to execute. Typically they are used as a way for a thread to report its result back to the main thread when it's complete.
Q1) What are their effects When they are used in 1) Activity 2) Service
There is no difference between the way these two items behave in a service or an activity in general except that a service can exist in its own process if android is instructed to do so. Threads in different processes can not directly talk to one another. Services are there to share data,functionality and in some cases threads between activities. There is no requirement for them to have their own thread.
The one major point to note is that only the main thread can update the UI (activity).
Also networking specifically can not be done on the main thread. Networking is usually done from within a service so that the results can be shared but this is not necessary.
The limitations around what must and must not be done in the main thread make threading a little tricky, but these limitations are there to help you avoid freezing the UI unexpectedly.
Q2) What is difference between them in context with their life span I am using following codes for them.
Difficult to answer as I don't understand the purpose of your code.
As an example. Android no longer allows you to do any networking on the main thread as this could freeze the UI while it's waiting for the server to respond over a poor wifi connection. To change something on the UI based on something retrieved from the network you must use a thread to do the networking and pass the data back to the main thread to update the UI.
A (doctored) snippet from my code looks like this:
private final Handler handler = new Handler();
#Override
protected void onCreate( Bundle savedInstanceState ) {
// irreverent to the example
super.onCreate(savedInstanceState);
super.setContentView(R.layout.abstract_main_view);
// Here's the example
Thread networkThread = new Thread() {
#Override
public void run() {
// This could take several seconds
final Collection<Player> players = service.lookupAllPlayers();
Runnable uiUpdate = new Runnable() {
#Override
public void run() {
// This is quick, just adding some text on the screen
showPlayers(players);
}
};
handler.post(uiUpdate);
}
};
networkThread.start();
}
In this example:
The handler is created and exists for the duration of this activity. Because this class is constructed by the main thread, the Handler is also. This means that all messages posted to this handler will be executed by main.
networkThread is created and started by the main thread in onCreate. This lives until it has retrieved the data from the network and posted a response back to the main thread. Then it's done.
The Runnable uiUpdate is created by networkThread once all data is retrieved. It does not have a thread associated and so does not execute right away. Instead it is posted back to main using the handler. It is then executed on the main thread and discarded once complete.
One can use a Handler to inform one thread of events from another thread.
Typical usage would be to inform the UI Thread from other threads.
We can not modify UI elements from other threads directly. So we can define a Handler as a member of an Activity instead.
Activities are created on the UI Thread so this handler also is on UI Thread.
So then from another thread we send a message to the Handler. And on receiving the message the Handler modifies some UI elements.
Recently, I show up a toast in user thread and got the above runtime error.
From Can't create handler inside thread that has not called Looper.prepare(), they proposed use Handler as solution. However, I saw the solution is quite lengthy and cumbersome.
My own solution is to use runOnUiThread
private void showTooDarkToastMessage()
{
((Activity) this.getContext()).runOnUiThread(new Runnable() {
#Override
public void run() {
Toast toast = Toast.makeText(getContext(), getResources().getString(R.string.toast_toodark), Toast.LENGTH_LONG);
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.show();
}
});
}
I was wondering, is there any shortcoming of using runOnUiThread, compared to Handler?
Because you are showing a UI element (a Toast message) runOnUiThread is perfect.
A Handler will run its task on the specified thread. For instance,
protected void onCreate( Bundle savedInstanceState )
{
Handler hander = new Handler();
//Create thread, post to handler
}
would create a new Handler that would run its posts on the UI thread. calling Activiy.runOnUiThread just posts the runnable specifically to the UI thread. By default, Handlers will run on whatever thread they were created in. The above code would work identical to using runOnUiThread because the onCreate method is run on the UI thread!
Handlers would be preferred if you needed to communicate between multiple background threads.
Because mobile devices have limited resources, work run on the UI thread should be kept relatively light. Intense work done on the UI thread can cause Application Not Responding (ANR) errors and can cause the OS to kill your process.
Actually runOnUiThread() using Handler inside. So, there is no downsides to use runOnUiThread() if you want to simple post some job to do in the UI Thread.
If you are interesting in difference between Handler and runOnUiThread() you can read about it in this answer