ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

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

2021-12-12 14:02:50  阅读:180  来源: 互联网

标签:FrameWork Handler Looper msg new android null Message


}
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 (;

标签:FrameWork,Handler,Looper,msg,new,android,null,Message
来源: https://blog.csdn.net/m0_65145113/article/details/121886613

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有