Looper、handler、message小结
来源:互联网 发布:一级位面淘宝网txt 编辑:程序博客网 时间:2024/06/03 03:20
Looper的作用:
Looper不断的获取Messagequeue中的一个message,然后由hander来处理
Looper.prepare();方法:为每个线程创建一个唯一的looper,并与当前线程联系起来。
Loop.prepare():这个方法只能调用一次,保证每个Thread只保存一个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的时候会创建一个MessageQueue(消息队列):
private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
Looper.loop();方法:
不断的获取MessageQueue的message,并通过message.taget.dispatchmessage(msg) 将消息发送出去。
/** * Run the message queue in this thread. Be sure to call * {@link #quit()} to end the 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 Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } msg.target.dispatchMessage(msg); 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(); } }
Hander:是如何与message联系起来的?
handler是怎么接收到message的?
/** * 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通过message.taget.dispatchmessage(msg) ,handler的dispatchMessage()方法如下:通过handlerMessage将消息发送处理。这里对消息的处理除了handlerMessage(),还有一个mCallback.handleMessage(msg),还有的是msg.callback:
所以handler处理消息的方法有三种,下面是常见两种,msg.callback用的比较少:
1.
handler = new Handler() {@Overridepublic void handleMessage(Message msg) {super.handleMessage(msg);}};2.
handler = new Handler(new Handler.Callback() {@Overridepublic boolean handleMessage(Message msg) {return false;}});
handler什么时候添加looper?
1:主线程的时候实例化handler时已经在ui主线程添加了looper,所以不用添加looper,而非主线程的时候实例化handler时必须添加looper,否则会报错误;throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
- new Thread()
- {
- private Handler handler;
- public void run()
- {
- Looper.prepare();
- handler = new Handler()
- {
- public void handleMessage(android.os.Message msg)
- {
- };
- };
- Looper.loop();
- }
这里,Looper只有两句代码,概括起来有三个步骤:
1.looper的准备工作(prepare)。这个使Looper与handler挂钩。
2.创建处理消息的hanler。
3.looper开始运作(loop)。不断的从消息队列中取出消息,发给hanler处理。
2.整个过程:
通过Looper.prepare();给当前线程保存一个唯一的Looper对象,该looper对象创建了一个Message队列。然后handler实例化时获取到当前线程的looper对象,并拿到该looper对象的消息队列。handler调用 sendMessage()方法过程中调用到enqueueMessage()方法,并将要发送的message的target指向当前的发送消息的handler,同时将消息压入要发送消息的handler的消息队列(也就是当前线程looper的消息队列,因为它于handler已经挂钩了),最后looper.loop();该方法不断获取到消息队列的Message,并通过message.taget.dispatchmessage(msg)将消息发送出去。handler可以通过handlerMessage()也可以通过Handler.Callback()获取到发送过来的Message,然后处理。
looper作用:创建当前线程的looper对象,该对象包含了一个消息队列,然后不断的获取消息队列的消息发送出去。
handler作用:获取到当前线程的looper的消息队列,发送消息时将消息的target(相当于要发送的地址)指定,并将消息压入消息队列中。
Handler发送消息有主要有两种,post系列、send系列:
post系列:
public final boolean post(Runnable r):
postAtTime(Runnable r, long uptimeMillis)
postDelayed(Runnable r, long delayMillis)
send系列主:要是发送message。
post可以设置发送时间,可以延迟发送,除了handler之外,View也有post的方法:
imageView.post(new Runnable() {@Overridepublic void run() {mAnimation.start(); }});
所以对一些view的ui操作可以通过post更新,其原理是:
View.post(Runnable)方法。在post(Runnable action)方法里,View获得当前线程(即UI线程)的Handler,然后将action对象post到Handler里。在Handler里,它将传递过来的action对象包装成一个Message(Message的callback为action),然后将其投入UI线程的消息循环中。在Handler再次处理该Message时,有一条分支(未解释的那条)就是为它所设,直接调用runnable的run方法。而此时,已经路由到UI线程里。
它们之间的关系:
1. Looper不断的获取Messagequeue中的一个message,然后由hander来处理
2.每个thread对应一个looper
3.每个looper只对应一个messagequeue
4.每个messagequeue中有多个message
5.每个message中最多指定一个handler来处理
- Looper、handler、message小结
- Looper,Handler,Message,MessageQueue
- Message,MessageQueue,Looper,Handler
- Looper Handler Message
- handler,message,Looper
- Looper,Handler,Message
- Handler Message Looper陈述
- Handler,Looper,Message
- Message Handler Looper
- Looper Handler Message
- Looper Handler Message 总结
- Message,Handler,Looper,MessageQueue
- Looper,Handler,Message
- Looper,Handler,Message
- Android Handler,Looper,Message
- Looper,Message,Handler概述
- Looper、Handler、Message
- Looper,Handler,Message
- org.tinygroup.ehcache-EhCache缓存解决方案
- Django第三方账号登录
- org.tinygroup.jcscache-JCS缓存解决方案
- org.tinygroup.templateweblayer-web层扩展
- C语言面试题大汇总之华为面试题
- Looper、handler、message小结
- org.tinygroup.cache-缓存接口
- jQuery html5Validate基于HTML5表单验证插件
- org.tinygroup.flowprocessor-流程加载器
- org.tinygroup.flow-流程引擎
- Arraysl类中的asList方法
- org.tinygroup.templateweb-模板文件处理器
- org.tinygroup.dbfilter
- org.tinygroup.templateengine-模板引擎