By Martín Zangl – Android Developer at Santex
Public Static Void Main
As we know, every single Java app starts with a call to method public static void main(). This is true for Java desktop, JEE servlets, and Android applications.
When Android boots, it uses a simple process called ZygoteInit. Zygote (Wikipedia) is a cell that can divide asexually by mitosis to produce identical offspring. This is a VM Dalvik process that loads the most common classes of the Android SDK on a thread, and then waits. When starting a new Android application, the Android system forks the ZygoteInit process. The thread in the child fork stops waiting and calls ActivityThread.main().
Here is what it’s essentially doing:
public class ActivityThread {
public static void main(String... args) {
Looper.prepare();
Looper.setMainLooper(Looper.myLooper());
Looper.loop();
}
}
Looper? What is a Looper?
Here we find a particular concurrency pattern called Thread-Specific Storage. This pattern allows multiple threads to use one “logical global” access point to retrieve an object that is local to a thread, without incurring locking overhead on each object access.
When an Android application starts, it creates a Looper object. A Looper object contains a static ThreadLocal object, a Message Queue, and the Thread reference that created it. In other words, a Looper implements a Thread-specific event loop. Using a Looper is a good way to process messages serially on one Thread.
Looper.prepare()
; This operation associates the Looper with the current thread and stores it in a static ThreadLocal.
Looper.loops()
; Will process each message in the queue, and block when the queue is empty.
As previously said, each Looper is associated with one thread. To retrieve the Looper associated with the current thread you can use the method Looper.myLooper().
An example of using a Looper with a Thread:
class HandlerThread extends Thread {
Looper looper;
public void run() {
Looper.prepare();
looper = Looper.myLooper();
Looper.loop();
}
}
Handlers is the natural companion to a Looper. Looper has a Message queue and Handlers put messages or runnable objects in place and process each of them, i.e. it allows them to send messages to a Looper message queue from any thread and handle messages dequeued on the thread associated with that Looper.
You can associate many handlers to one Looper. The Looper delivers the message to one specific handler.
A default Handler constructor associates it with the current thread and its Looper. We could define the other Looper, if we want, in order to post messages to the Message queue of whatever Looper we want.
The Looper referenced in the void main method is called Main Looper, part of the Main Thread. This particular thread is in charge of dispatching events to the UI widgets that include the drawing events. All components (other Activities, Services, Broadcast Receivers, and Content Providers) that run in the same process are referenced in the Main Thread.
When an application performs intensive work in response to user interactions, this single thread model can yield poor performance. If everything is happening in the Main Thread it will block the whole UI, so no events can be dispatched, including drawing events. That is when a ANR (Application Not Responding) dialog appears. In that case, we just put all the long background operations in another thread, but other problems arise in paradise, only the main thread can process UI widgets. So, we need to somehow handle communication between threads.
In the next post we’ll talk about:
Using custom handlers and other threads
Asynctasks
Loaders
IntentServices
About the Author – Martín Zangl is an experienced Android Developer at Santex, passionate about his work. Martín is continuously learning and training to investigate new technologies.
Source:
https://corner.squareup.com/2013/10/android-main-thread-1.html
http://developer.android.com/reference/android/os/Looper.html
http://developer.android.com/guide/components/processes-and-threads.html