1.new Message()与Message.obtain()的区别
前者直接创建新的对象,后者如果有可重复利用的实例会从全局池直接复用,没有的话重新创建实例,可以避免分配新的对象
2.mHandler.sendMessage(Message.obtain()); 与的区别mHandler.sendMessageDelayed(Message.obtain(),1000);
实际上都是调用了 (@NonNull Message msg, long uptimeMillis)方法,
updatime实际上是SystemClock.uptimeMillis() + delayMillis,传递的时间拼加上系统时间,也就是实际执行的时间
3.sendmessageAtTime(@NonNull Message msg, long uptimeMillis)
调用enqueueMessage方法,去将message添加到MessageEnqueue中
4.MessageEnqueue的enqueueMessage方法
MessageEnqueue实际上是一个链表,为什么使用链表?因为插入和删除快
![](img\Image [2].png)
以下是插入链表的方法,
1)如果插入的执行时间小于链表第一个时间,就把当前message设置为第一个,然后当前message的next指向原来的next
2)否则进入一个死循环,一旦找到一个比当前时间大的message,就把message插入到中间,然后跳出循环,如果p.next没有了,就直接插入到最后
![](img\Image [1].png)
5.那是怎么执行的呢?
这里涉及到activity的启动流程,在ActivityThread中有一个man函数,主要代码如下
public static void main(String[] args) {
//省略部分代码
Looper.prepareMainLooper();
//省略部分代码
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
//省略部分代码
Looper.loop();
}
Looper.prepareMainLooper() 创建了一个 Looper 对象,而且保证一个线程只有一个 Looper
一旦启动就进入了loop死循环,不断的从 MessageQueue 中去获取message
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;
//省略部分代码
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
//省略部分代码
try {
//执行messag
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
if (observer != null) {
observer.dispatchingThrewException(token, msg, exception);
}
throw exception;
} finally {
ThreadLocalWorkSource.restore(origWorkSource);
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
//省略部分代码
//释放资源
msg.recycleUnchecked();
}
}
手动写一共简单的Handler框架,demo一共有以下类
![](img\Image [3].png)
其中textview的代码为
public class TextView {
private Thread mThread;
public TextView() {
//记录创建时的线程
this.mThread = Thread.currentThread();
}
public void setText(String text) {
//检测线程是否为建立时的线程
// checkThread();
System.out.println(text);
}
void checkThread() {
if (mThread != Thread.currentThread()) {
throw new RuntimeException(
"Only the original thread that created a view hierarchy can touch its views.");
}
}
}
main方法中执行的代码为
new Thread(() -> {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//直接在子线程中设置
// textView.setText("线程名称->" + Thread.currentThread().getName());
//通过hanlder设置
Message message = new Message();
mHandler.sendMessage(message);
}).start();
验证结果
1)注释checkThread更新内容,显示线程0
![](img\Image [4].png)
2)取消注释checkThread更新内容,抛异常
![](img\Image [5].png)
3)使用handler发送消息更新内容,结果正常,在主线程主
![](img\Image [6].png)
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。