热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Androidhandler详解

一、Looperlooper是关联message与handler的重要部分。你在Android的子线程中newhandler为啥报错,和looper关系不浅

一、Looper
looper是关联message与handler的重要部分。

你在Android的子线程中new handler为啥报错,和looper关系不浅,据如下个例子,在子线程中调用handler

new Thread(new Runnable() { public void run() { Looper.prepare(); Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { Toast.makeText(getApplicationContext(), "handler msg", Toast.LENGTH_LONG).show(); } }; handler.sendEmptyMessage(1); Looper.loop(); }; }).start();
或者在子线程直接使用Looper.getMainLooper();new Thread(new Runnable() { public void run() { Handler handler = new Handler(Looper.getMainLooper()){ @Override public void handleMessage(Message msg) { Toast.makeText(getApplicationContext(), "handler msg", Toast.LENGTH_LONG).show(); } }; handler.sendEmptyMessage(1); }; }).start();

Looper.getMainLooper()实际就是主线程的looper,主线程默认都会创建looper

创建looper时会创建messagequeue

注:每一个线程只能有一个looper,looper是线程持有

Looper实际上是给当前子线程建立的looper,为了能够遍历当前子线程的消息队列,

源码

public static void loop() {final Looper me &#61; myLooper();if (me &#61;&#61; null) {throw new RuntimeException("No Looper; Looper.prepare() wasn&#39;t called on this thread.");}final MessageQueue queue &#61; 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 &#61; Binder.clearCallingIdentity();for (;;) {Message msg &#61; queue.next(); // might blockif (msg &#61;&#61; 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 loggerfinal Printer logging &#61; me.mLogging;if (logging !&#61; null) {logging.println(">>>>> Dispatching to " &#43; msg.target &#43; " " &#43;msg.callback &#43; ": " &#43; msg.what);}final long slowDispatchThresholdMs &#61; me.mSlowDispatchThresholdMs;final long traceTag &#61; me.mTraceTag;if (traceTag !&#61; 0 && Trace.isTagEnabled(traceTag)) {Trace.traceBegin(traceTag, msg.target.getTraceName(msg));}final long start &#61; (slowDispatchThresholdMs &#61;&#61; 0) ? 0 : SystemClock.uptimeMillis();final long end;try {msg.target.dispatchMessage(msg);end &#61; (slowDispatchThresholdMs &#61;&#61; 0) ? 0 : SystemClock.uptimeMillis();} finally {if (traceTag !&#61; 0) {Trace.traceEnd(traceTag);}}if (slowDispatchThresholdMs > 0) {final long time &#61; end - start;if (time > slowDispatchThresholdMs) {Slog.w(TAG, "Dispatch took " &#43; time &#43; "ms on "&#43; Thread.currentThread().getName() &#43; ", h&#61;" &#43;msg.target &#43; " cb&#61;" &#43; msg.callback &#43; " msg&#61;" &#43; msg.what);}}if (logging !&#61; null) {logging.println("<<<< &#43; msg.target &#43; " " &#43; msg.callback);}// Make sure that during the course of dispatching the// identity of the thread wasn&#39;t corrupted.final long newIdent &#61; Binder.clearCallingIdentity();if (ident !&#61; newIdent) {Log.wtf(TAG, "Thread identity changed from 0x"&#43; Long.toHexString(ident) &#43; " to 0x"&#43; Long.toHexString(newIdent) &#43; " while dispatching to "&#43; msg.target.getClass().getName() &#43; " "&#43; msg.callback &#43; " what&#61;" &#43; msg.what);}msg.recycleUnchecked();}}

二、MessageQueue
MessageQueue是一个消息队列&#xff0c;用于存放message&#xff0c;looper来把其中的message发送到handlermessage

采用先进先出的方式来管理message&#xff0c;内部采用单链表来进行维护&#xff0c;插入删除比较快

三、Message
就是咱最常用的消息了&#xff0c;按照我上面的说法建议使用Message.obtain()来获取Message实例&#xff0c;应为message有个pool

源码

public static Message obtain() {synchronized (sPoolSync) {if (sPool !&#61; null) {Message m &#61; sPool;sPool &#61; m.next;m.next &#61; null;m.flags &#61; 0; // clear in-use flagsPoolSize--;return m;}}return new Message();}


推荐阅读
author-avatar
imba-Y_685
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有