青春须早为,岂能长少年。这篇文章主要讲述深入解析Android中Handler消息机制相关的知识,希望能为你提供帮助。
android提供了Handler 和 Looper 来满足线程间的通信。Handler先进先出原则。Looper类用来管理特定线程内对象之间的消息交换(MessageExchange)。Handler消息机制可以说是Android系统中最重要部分之一,
所以,
本篇博客我们就来深入解析Android中Handler消息机制。
Handler的简单使用 为什么系统不允许子线程更新UI
因为的UI控件不是线程安全的。
如果在多线程中并发访问可能会导致UI控件处于不可预期的状态,
那为什么不对UI控件的访问加上上锁机制呢?
因为有这么两个缺点:
1.上锁会让UI控件变得复杂和低效
2.上锁后会阻塞某些进程的执行
对于手机系统来说,
这两个缺点是不可接受的,
所以最简单高效的方法就是 —— 采用单线程模型来处理UI操作。
对开发者而言也不是很麻烦,
只是通过Handler切换一下访问的线程的就好。
Handler的简单使用
既然子线程不能更改界面,
那么我们现在就借助Handler让我们更改一下界面:
主要步骤是这样子的:
1.new出来一个Handler对象,
复写handleMessage方法
2.在需要执行更新UI的地方 sendEmptyMessage 或者 sendMessage
3.在handleMessage里面的switch里面case不同的常量执行相关操作
public class MainActivity extends ActionBarActivity {private TextView mTextView;
private Handler mHandler;
private static final int UI_UPDATE1 =
0;
private static final int UI_UPDATE2 =
1;
@
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mHandler =
new Handler() {@
Override
public void handleMessage(Message msg) {
switch (msg.what) {
case UI_UPDATE1:
mTextView.setText("
通过Handler方法1修改UI"
);
break;
case UI_UPDATE2:
mTextView.setText("
通过Handler方法2修改UI"
);
break;
}
}};
mTextView =
(TextView) findViewById(R.id.textview);
mTextView.setOnClickListener(new OnClickListener() {@
Override
public void onClick(View v) {
Log.d("
Test"
, "
点击文字"
);
updateUi();
}
});
}protected void updateUi() {
new Thread(new Runnable() {@
Override
public void run() {
// 方式一和方式二可以达到相同的效果,就是更改界面
//方式一
//mHandler.sendEmptyMessage(UI_UPDATE1);
//方式二
Message msg =
Message.obtain();
msg.what =
UI_UPDATE2;
mHandler.sendMessage(msg);
}
}).start();
}
}
<
RelativeLayout xmlns:android=
"
http://schemas.android.com/apk/res/android"
xmlns:tools=
"
http://schemas.android.com/tools"
android:layout_width=
"
match_parent"
android:layout_height=
"
match_parent"
tools:context=
"
com.example.handlerdemo3.MainActivity"
>
<
TextView
android:id=
"
@
+
id/textview"
android:layout_width=
"
wrap_content"
android:layout_height=
"
wrap_content"
android:text=
"
@
string/hello_world"
android:layout_centerInParent=
"
true"
android:clickable=
"
true"
/>
<
/RelativeLayout>
消息机制的分析理解 安卓的异步消息处理机制就是handler机制。
主线程, ActivityThread被创建的时候就会创建Looper
Looper被创建的时候创建MessageQueue。
也就是说主线程会直接或间接创建出来Looper和MessageQueue。
Handler的工作机制简单来说是这样的
1.Handler发送消息仅仅是调用MessageQueue的enqueueMessage向插入一条信息到MessageQueue
2.Looper不断轮询调用MeaasgaQueue的next方法
3.如果发现message就调用handler的dispatchMessage, dispatchMessage被成功调用, 接着调用handlerMessage()
文章图片
Handler消息机制的源码分析 ThreadLocal工作原理
首先, ThreadLocal 不是用来解决共享对象的多线程访问问题的, 一般情况下, 通过ThreadLocal.set() 到线程中的对象是该线程自己使用的对象, 其他线程是不需要访问的, 也访问不到的。各个线程中访问的是不同的对象。
另外, 说ThreadLocal使得各线程能够保持各自独立的一个对象, 并不是通过ThreadLocal.set()来实现的, 而是通过每个线程中的new 对象 的操作来创建的对象, 每个线程创建一个, 不是什么对象的拷贝或副本。通过ThreadLocal.set()将这个新创建的对象的引用保存到各线程的自己的一个map中, 每个线程都有这样一个map, 执行ThreadLocal.get()时, 各线程从自己的map中取出放进去的对象, 因此取出来的是各自自己线程中的对象, ThreadLocal实例是作为map的key来使用的。
如果ThreadLocal.set()进去的东西本来就是多个线程共享的同一个对象, 那么多个线程的ThreadLocal.get()取得的还是这个共享对象本身, 还是有并发访问问题。
我们看一下ThreadLocal的set方法
public void set(T value) {
Thread currentThread =
Thread.currentThread();
Values values =
values(currentThread);
if (values =
=
null) {
values =
initializeValues(currentThread);
}
values.put(this, value);
}
查看values方法里面做了什么
Values values(Thread current) {
return current.localValues;
}
通过上面代码我们可以知道, 当values为空的时候, 才调用initializeValues方法进行初始化, 查看inheritValues相关逻辑:
private void inheritValues(Values fromParent) {
// Transfer values from parent to child thread.
Object[] table =
this.table;
for (int i =
table.length - 2;
i >
=
0;
i -=
2) {
Object k =
table[i];
if (k =
=
null || k =
=
TOMBSTONE) {
// Skip this entry.
continue;
}// The table can only contain null, tombstones and references.
Reference<
InheritableThreadLocal<
?>
>
reference
=
(Reference<
InheritableThreadLocal<
?>
>
) k;
// Raw type enables us to pass in an Object below.
InheritableThreadLocal key =
reference.get();
if (key !=
null) {
// Replace value with filtered value.
// We should just let exceptions bubble out and tank
// the thread creation
table[i +
1] =
key.childValue(fromParent.table[i +
1]);
} else {
// The key was reclaimed.
table[i] =
TOMBSTONE;
table[i +
1] =
null;
fromParent.table[i] =
TOMBSTONE;
fromParent.table[i +
1] =
null;
tombstones+
+
;
fromParent.tombstones+
+
;
size--;
fromParent.size--;
}
}
}
其实就是各种赋值table数组, 进行初始化
最后才是调用values.put(this, value)把ThreadLocal和value一起保存, 我们可以看一下values.put(this, value)方法
void put(ThreadLocal<
?>
key, Object value) {
cleanUp();
// Keep track of first tombstone. That'
s where we want to go back
// and add an entry if necessary.
int firstTombstone =
-1;
for (int index =
key.hash &
mask;
;
index =
next(index)) {
Object k =
table[index];
if (k =
=
key.reference) {
// Replace existing entry.
table[index +
1] =
value;
return;
}if (k =
=
null) {
if (firstTombstone =
=
-1) {
// Fill in null slot.
table[index] =
key.reference;
table[index +
1] =
value;
size+
+
;
return;
}// Go back and replace first tombstone.
table[firstTombstone] =
key.reference;
table[firstTombstone +
1] =
value;
tombstones--;
size+
+
;
return;
}// Remember first tombstone.
if (firstTombstone =
=
-1 &
&
k =
=
TOMBSTONE) {
firstTombstone =
index;
}
}
}
可以看出, Threadlocal的值在table数组的存储位置总是reference的下一个位置.
接下来, 查看Threadlocal的get方法
文章图片
Get方法的逻辑是: 通过values方法取出当前线程的localValues对象, 如果为null, 就返回初始值。如果localValues不为null, 取出其table数组, 如果reference等于table数组index角标的值, 就在table[index + 1]取出其Threadlocal值。
MessageQueue工作原理
MessageQueue中文翻译就是消息队列, 它内部存储了一组信息, 存放的是Message, 以队列的形式对外提供了插入和删除的工作( 虽然名字叫做队列, 但是其内部的 存储结构是单链表)
主要 插入 和 读取 两个操作, 这两个操作对应着两个方法:
插入(
入队)
enqueueMessage(Message msg, long when)
读取(
出队)
next()
查看enqueueMessage的源码:
boolean enqueueMessage(Message msg, long when) {
if (msg.isInUse()) {
throw new AndroidRuntimeException(msg +
"
This message is already in use."
);
}
if (msg.target =
=
null) {
throw new AndroidRuntimeException("
Message must have a target."
);
}boolean needWake;
synchronized (this) {
if (mQuiting) {
RuntimeException e =
new RuntimeException(
msg.target +
"
sending message to a Handler on a dead thread"
);
Log.w("
MessageQueue"
, e.getMessage(), e);
return false;
}msg.when =
when;
Message p =
mMessages;
if (p =
=
null || when =
=
0 || when <
p.when) {
// New head, wake up the event queue if blocked.
msg.next =
p;
mMessages =
msg;
needWake =
mBlocked;
} else {
// Inserted within the middle of the queue.Usually we don'
t have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake =
mBlocked &
&
p.target =
=
null &
&
msg.isAsynchronous();
Message prev;
for (;
;
) {
prev =
p;
p =
p.next;
if (p =
=
null || when <
p.when) {
break;
}
if (needWake &
&
p.isAsynchronous()) {
needWake =
false;
}
}
msg.next =
p;
// invariant: p =
=
prev.next
prev.next =
msg;
}
}
if (needWake) {
nativeWake(mPtr);
}
return true;
从enqueueMessage的实现来看, 主要操作就是单链表的插入操作, 接下来查看next方法的实现:
Message next() {
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
// which is not supported.
final long ptr =
mPtr;
if (ptr =
=
0) {
return null;
}int pendingIdleHandlerCount =
-1;
// -1 only during first iteration
int nextPollTimeoutMillis =
0;
for (;
;
) {
if (nextPollTimeoutMillis !=
0) {
Binder.flushPendingCommands();
}nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message.Return if found.
final long now =
SystemClock.uptimeMillis();
Message prevMsg =
null;
Message msg =
mMessages;
if (msg !=
null &
&
msg.target =
=
null) {
// Stalled by a barrier.Find the next asynchronous message in the queue.
do {
prevMsg =
msg;
msg =
msg.next;
} while (msg !=
null &
&
!msg.isAsynchronous());
}
if (msg !=
null) {
if (now <
msg.when) {
// Next message is not ready.Set a timeout to wake up when it is ready.
nextPollTimeoutMillis =
(int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked =
false;
if (prevMsg !=
null) {
prevMsg.next =
msg.next;
} else {
mMessages =
msg.next;
}
msg.next =
null;
if (DEBUG) Log.v(TAG, "
Returning message: "
+
msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
nextPollTimeoutMillis =
-1;
}// Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
}// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
if (pendingIdleHandlerCount <
0
&
&
(mMessages =
=
null || now <
mMessages.when)) {
pendingIdleHandlerCount =
mIdleHandlers.size();
}
if (pendingIdleHandlerCount <
=
0) {
// No idle handlers to run.Loop and wait some more.
mBlocked =
true;
continue;
}if (mPendingIdleHandlers =
=
null) {
mPendingIdleHandlers =
new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers =
mIdleHandlers.toArray(mPendingIdleHandlers);
}// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i =
0;
i <
pendingIdleHandlerCount;
i+
+
) {
final IdleHandler idler =
mPendingIdleHandlers[i];
mPendingIdleHandlers[i] =
null;
// release the reference to the handlerboolean keep =
false;
try {
keep =
idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "
IdleHandler threw exception"
, t);
}if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}// Reset the idle handler count to 0 so we do not run them again.
pendingIdleHandlerCount =
0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
nextPollTimeoutMillis =
0;
}
}
从上面代码可以得出以下结论:
1.next方法是一个无限循环的方法, 如果消息队列中没有消息, 那么next方法会一直阻塞
2.当有新消息到来, next方法会返回这条消息, 并将其从单链表中移除。
Looper的工作原理
Looper是一个轮询器, 它的作用不断轮询MessageQueue, 当如果有新的消息就交给Handler处理, 如果轮询不到新的消息, 那就自身就处于阻塞状态。
查看Looper类的源码, 可以发现的他的构造方法里面创建了一个MessageQueue, 然后将当前线程的对象保存起来
private Looper(boolean quitAllowed) {
mQueue =
new MessageQueue(quitAllowed);
mThread =
Thread.currentThread();
}
在Looper的构造方法中初始化了一个消息队列MessageQueue和一个线程Thread。从这可看出: 一个Looper对应着一个消息队列以及当前线程。
当收到消息Message后系统会将其存入消息队列中等候处理。至于Looper, 它在Android的消息机制中担负着消息轮询的职责, 它会不间断地查看MessageQueue中是否有新的未处理的消息; 若有则立刻处理, 若无则进入阻塞。
相信大家一定有遇到过, 在子线程中创建Handler会报如下错误
文章图片
解决办法就是new Handler的时候加上Looper.prepare();
而Looper.prepare()的内部实现逻辑就是创建一个Looper
public static void prepare() {
prepare(true);
}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));
}
线程默认是没有Looper的, 但是为什么在主线程没有创建的Looper就可以使用Handler? 主线程是特别的。主线程, 也就是ActivityThread, 当主线程被创建的时候, 会调用Looper内的prepareMainLooper方法, 创建Looper, 该方法是专门给主线程创建Looper用的。也正因为这点, 所以我们在主线程创建了Handler就直接能用了。
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper !=
null) {
throw new IllegalStateException("
The main Looper has already been prepared."
);
}
sMainLooper =
myLooper();
}
}
由于这个特殊性, Looper还提供了一个getMainLooper方法, 使得可以在任何地方获取主线程的Looper。
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
接下来, 我们看一下Looper的退出
Looper提供了两个方法进行退出操作, 分别是quit和quitSafely,他们调用的是MessageQueue的quit方法
public void quit() {
mQueue.quit(false);
}
public void quitSafely() {
mQueue.quit(true);
}
MessageQueue的quit方法:
void quit(boolean safe) {
if (!mQuitAllowed) {
throw new IllegalStateException("
Main thread not allowed to quit."
);
}synchronized (this) {
if (mQuitting) {
return;
}
mQuitting =
true;
if (safe) {
removeAllFutureMessagesLocked();
} else {
removeAllMessagesLocked();
}// We can assume mPtr !=
0 because mQuitting was previously false.
nativeWake(mPtr);
}
}
如果调用Looper.quit方法, 最终会调用removeAllMessagesLocked方法, 该方法逻辑: 直接遍历所有的消息, 并将消息强制回收
private void removeAllMessagesLocked() {
Message p =
mMessages;
while (p !=
null) {
Message n =
p.next;
p.recycleUnchecked();
p =
n;
}
mMessages =
null;
}
如果调用Looper.quitSafely方法, 最终会调removeAllFutureMessagesLocked方法, 该方法逻辑:
void removeCallbacksAndMessages(Handler h, Object object) {
if (h =
=
null) {
return;
}synchronized (this) {
Message p =
mMessages;
// Remove all messages at front.
while (p !=
null &
&
p.target =
=
h
&
&
(object =
=
null || p.obj =
=
object)) {
Message n =
p.next;
mMessages =
n;
p.recycleUnchecked();
p =
n;
}// Remove all messages after front.
while (p !=
null) {
Message n =
p.next;
if (n !=
null) {
if (n.target =
=
h &
&
(object =
=
null || n.obj =
=
object)) {
Message nn =
n.next;
n.recycleUnchecked();
p.next =
nn;
continue;
}
}
p =
n;
}
}
}
【深入解析Android中Handler消息机制】一个无限for循环, 只有n.when > now和n = = null才会跳出循环, 说明是等消息队列中已有的消息处理完毕后, 才会跳出, 然后执行回收。
Looper这个类里面最重要的方法就是loop()开启消息循环这个方法了, 看一下loop代码的实现逻辑:
public static void loop() {
final Looper me =
myLooper();
if (me =
=
null) {
throw new RuntimeException("
No Looper;
Looper.prepare() wasn'
t called on this thread."
);
}
final MessageQueue queue =
me.mQueue;
// Make sure the identity of this thread is that of the local process,
// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
final long ident =
Binder.clearCallingIdentity();
for (;
;
) {
Message msg =
queue.next();
// might block
if (msg =
=
null) {
// No message indicates that the message queue is quitting.
return;
}// This must be in a local variable, in case a UI event sets the logger
final Printer logging =
me.mLogging;
if (logging !=
null) {
logging.println("
>
>
>
>
>
Dispatching to "
+
msg.target +
"
"
+
msg.callback +
"
: "
+
msg.what);
}final long traceTag =
me.mTraceTag;
if (traceTag !=
0) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag !=
0) {
Trace.traceEnd(traceTag);
}
}if (logging !=
null) {
logging.println("
<
<
<
<
<
Finished to "
+
msg.target +
"
"
+
msg.callback);
}// Make sure that during the course of dispatching the
// identity of the thread wasn'
t corrupted.
final long newIdent =
Binder.clearCallingIdentity();
if (ident !=
newIdent) {
Log.wtf(TAG, "
Thread identity changed from 0x"
+
Long.toHexString(ident) +
"
to 0x"
+
Long.toHexString(newIdent) +
"
while dispatching to "
+
msg.target.getClass().getName() +
"
"
+
msg.callback +
"
what=
"
+
msg.what);
}msg.recycleUnchecked();
}
}
通过代码我们知道: looper方法是一个死循环, 唯一跳出的循环的方式是MessageQueue的next方法返回null, 但这几乎不可能, 因为在MessageQueue的next方法中, 假如没有消息加入队列, next方法会一直阻塞, 不会返回null。如果我们不手动调用quit或者quitSafely方法的话, MessageQueue的next方法是不可能返回null的。
当MessageQueue没有消息时, next方法会一直阻塞在那里, 因为MessageQueue的next方法阻塞了, 就导致Looper的loop方法也一直在阻塞了。
这里我们那一分为二的谈,
loop轮询不到消息: 那么处于阻塞状态, 然后就没有然后了, 除了又轮询到了新的消息
loop轮到了新的消息: Looper就会处理消息
1、msg.target.dispatchMessage(msg), 这里的 msg.target就是指Handler对象
2、到了最后, Handler发送的消息又交给了自己的dispatchMessage方法来处理了。( 这个dispatchMessage方法不是Handler自己调用时, 是与Handler相相关的Looper间接调用的) , 这样下来, 就成功地将逻辑切换到指定的线程当中去了
Handler的工作原理
Handler的主要工作: 消息的 发送 和 接收 。Handler消息发送的形式有post和send两种。
查看Handler中sendMessage代码
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
sendMessage调用sendMessageDelayed
public final boolean sendMessageDelayed(Message msg, long delayMillis)
{
if (delayMillis <
0) {
delayMillis =
0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() +
delayMillis);
}
sendMessageDelayed调用sendMessageAtTime
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue =
mQueue;
if (queue =
=
null) {
RuntimeException e =
new RuntimeException(
this +
"
sendMessageAtTime() called with no mQueue"
);
Log.w("
Looper"
, e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
sendMessageAtTime调用enqueueMessage
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target =
this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
boolean enqueueMessage(Message msg, long when) {
if (msg.target =
=
null) {
throw new IllegalArgumentException("
Message must have a target."
);
}
if (msg.isInUse()) {
throw new IllegalStateException(msg +
"
This message is already in use."
);
}synchronized (this) {
if (mQuitting) {
IllegalStateException e =
new IllegalStateException(
msg.target +
"
sending message to a Handler on a dead thread"
);
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}msg.markInUse();
msg.when =
when;
Message p =
mMessages;
boolean needWake;
if (p =
=
null || when =
=
0 || when <
p.when) {
// New head, wake up the event queue if blocked.
msg.next =
p;
mMessages =
msg;
needWake =
mBlocked;
} else {
// Inserted within the middle of the queue.Usually we don'
t have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake =
mBlocked &
&
p.target =
=
null &
&
msg.isAsynchronous();
Message prev;
for (;
;
) {
prev =
p;
p =
p.next;
if (p =
=
null || when <
p.when) {
break;
}
if (needWake &
&
p.isAsynchronous()) {
needWake =
false;
}
}
msg.next =
p;
// invariant: p =
=
prev.next
prev.next =
msg;
}// We can assume mPtr !=
0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
得出结论: Handler的发送消息仅仅是调用MessageQueue的enqueueMessage向插入一条信息到MessageQueue, MessageQueue就会返回这条消息给Looper, Looper会交给msg.target.dispatchMessage(msg)方法处理, 就进入消息处理阶段。
查看dispatchMessage方法
/**
* 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);
}
}
首先, 判断 Message. Callback是否为null,不为null, 就调用handleCallback方法
private static void handleCallback(Message message) {
message.callback.run();
}
Callback是一个Runnable对象, 实际上就是post方法传递的Runnable参数。
其次, 检查mCallback是否为null, 如果不为null就调用mCallback.handleMessage方法, 查看mCallback.handleMessage方法
public interface Callback {
public boolean handleMessage(Message msg);
}
源码中注释已经对Callback进行了解释:
可以用来创建一个Handler的实例但不需要派生Handler的子类
在日常开发中, 创建Handler最常见的方式就是派生一个Handler的子类并重写handleMessage方法来处理具体的消息, 而Callback给我们提供了另外一种方式, 不需要派生Handler的子类。
最后, 调用Handler的handleMessage方法, 这就是我们平时写Handler要实现的方法
文章图片
主线程的消息循环
Android的主线程就是ActivityThread, 主线程的路口方法是main方法, 在 main中系统会通过Looper.prepareMainLooper()来创建主线程的Looper以及MessageQueue, 并通过Looper.loop()开启主线程消息循环
public static void main(String[] args) {
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy.We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
Security.addProvider(new AndroidKeyStoreProvider());
Process.setArgV0("
<
pre-initialized>
"
);
Looper.prepareMainLooper();
ActivityThread thread =
new ActivityThread();
thread.attach(false);
if (sMainThreadHandler =
=
null) {
sMainThreadHandler =
thread.getHandler();
}AsyncTask.init();
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "
ActivityThread"
));
}Looper.loop();
throw new RuntimeException("
Main thread loop unexpectedly exited"
);
}
主线程开始循环后, ActivityThread还需要一个Handler来和消息队列进行交互, 这个Handler就是ActivityThread.H
文章图片
ApplicationThread通过binder与Ams通信,并将Ams的调用,通过H类(也就是Hnalder)将消息发送到消息队列,然后进行相应的操作, H收到消息后, 就会将ApplicationThread中逻辑切换到ActivityThread中执行, 也就是主线程中执行, 这个过程就是主线程的消息循环。
至此, Handler消息机制就分析完毕, 如有错漏, 欢迎留言指证。
推荐阅读
- Android应用性能优化系列视图篇——隐藏在资源图片中的内存杀手
- Android应用程序如何使用Internet资源()
- Android应用程序的结构和解析
- Android源代码下载 “Gerrit下载源代码”
- Android开发(《Gradle Recipes for Android》阅读笔记(翻译)3.3——整合resource文件)
- Android中的WeakReference 弱引用
- Android全平台书籍
- Android的Launcher启动流程 “Launcher部分启动流程”
- Android系统源代码目录结构 “Android源代码”“目录结构”