Processes and threads
- Process: A process is a running instance of a program.
- Thread: Thread is a basic unit of CPU scheduling.
- Android:
- The four major components are only some "parts" in the process.
- After the application starts, at least one main thread, Activity Thread, and two Binder threads are created.
- Components in the same package will run in the same process space.
- Components in different packages can run in the same process space in a certain way (IPC).
II. The Direct Relations of Thread, Looper, Message and Hanlder
1. A thread Thread corresponds to a Looper
private static void prepare(boolean quitAllowed) { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper(quitAllowed)); } private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
In a thread, Looper.prepare(), which creates a MessageQueue(), specifies that the thread of Looper is the current thread.
2. A Looper corresponds to a MessageQueue
That's enough.
3. Each MessageQueue has N Messages
That's enough.
4. Each Messag specifies at most one Hanlder to handle
public Handler(Callback callback, boolean async) { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper();//mLooper of the current thread if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue;//This Looper mQueue mCallback = callback; mAsynchronous = async; }
We can find a new Hanlder in a thread Thread, which will find the mLooper of the current thread and the mQueue of the Looper.
/** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { } /** * Handle system messages here. */ public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
The above is the default strategy for distributing and executing messages, and of course you can override your customizations. The final execution is handle Message (msg).
Thread and Hanlder are one-to-many relationships
As we can see above, we can have more than one Hanlder in a Thread. The Hanlder will find the only Looper in the current Thead public and the only MessageQueue in the Looper. We can press some messages into the MessageQueue through the Hanlder. The Looper takes out messages one by one from the Queue and handles them to Hanlder.
summary
We can think of an App as an application. The starter will start a process by default. When the process starts, zygoteInit will start a main thread, two binder threads and some of our own new sub-threads. This main thread is ActivityThread(Service is also hosted in ActivityThread). Then through the above-mentioned Hadler, Looper, MessageQueue, let the program live.