FrameWork内核解析之Handler消息机制(二),android学习视频

}
Message message = handler.obtainMessage();
message.obj = “Hi MeiMei”;
handler.sendMessage(message);
}
};
hanMeiMeiThread.setName(“韩梅梅 Thread”);
hanMeiMeiThread.start();
liLeiThread.setName(“李雷 Thread”);
liLeiThread.start();

/*

  • 搞定,我们创建了两个Thread,liLeiThread和hanMeiMeiThread两个线程,很熟悉的名字啊!
  • 跟之前的代码没太大区别hanMeiMeiThread创建了Handler,liLeiThread通过Handler发送了消息。
  • 只不过此处我们只发送一个消息,所以没有使用what来进行标记
  • 运行看看,我们的李雷能拨通梅梅吗?
  • 啊哦,出错了
  • 05-13 17:08:17.709 20673-20739/? E/AndroidRuntime: FATAL EXCEPTION: 韩梅梅 Thread
    Process: design.wang.com.designpatterns, PID: 20673
    java.lang.RuntimeException: Can’t create handler inside thread that has not called Looper.prepare()
    at android.os.Handler.(Handler.java:200)
    at android.os.Handler.(Handler.java:114)
    *Can’t create handler inside thread that has not called Looper.prepare()
  • -----------》它说我们创建的handler没有调用Looper.prepare();
  • 好的,我们在实例化Handler之前调用下该方法,看一下。加上是不是没有报错了呢。
  • 等等,虽然没有报错,但是hanMeiMeiThread也没有接到消息啊,消息呢?别急。
  • 我们在Handler实例化之后加上Looper.loop();看一看,运行一下,是不是收到消息了呢。
  • 这是为什么呢?
  • 接下来我们就去看看Handler是怎么实现的发消息呢,弄清楚了原理,这里的原因也就明白了。
    */

}

接下来我们看下,为什么在子线程里实例化的时候不调用Looper.prepare()就会报错呢?

//我们先来看看new Handler();时出错的原因。后续讲解源码分析只贴出关键部分。
//如下是Handler构造函数里抛出上文异常的地方,可以看到,由于mLooper对象为空才抛出的该异常。
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
“Can’t create handler inside thread that has not called Looper.prepare()”);
}
/*
异常的原因看到了,接下来我们看看Looper.prepare()方法都干了些什么?
*/
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));
}
/*
可以看到,该方法在当前thread创建了一个Looper(), ThreadLocal主要用于维护线程的本地变量,
*/
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
//而Looper的构造函数里面又为我们创建了一个MessageQueue()对象。

了解到此,我们已经成功引出了Handler机制几个关键的对象了,Looper、MessageQueue、Message。
为什么在主线程中创建Handler不需要要用Looper.prepare()和Looper.loop()方法呢?
其实不是这样的,App初始化的时候都会执行ActivityThread的main方法,我们可以看看ActivityThread的main()方法都做了什么!

Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, “ActivityThread”));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
/*
真相只有一个,是的在创建主线程的时候Android已经帮我们调用了Looper.prepareMainLooper()
和Looper.loop()方法,所以我们在主线程能直接创建Handler使用。
*/

我们接着来看Handler发送消息的过程:

//调用Handler不同参数方法发送Message最终都会调用到该方法
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);
}

sendMessage的关键在于enqueueMessage(),其内部调用了messageQueue的enqueueMessage方法

boolean enqueueMessage(Message msg, long when) {

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 {
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;

上一篇:HandlerThread源码分析,androidjetpack视频


下一篇:即刻到位 快速落地 Amazon 智能工厂解决方案