Message Handler Looper
来源:互联网 发布:怎样与淘宝买家联系 编辑:程序博客网 时间:2024/05/24 07:46
一、Message
Message创建方式有两种,一种是new Message(),开销较大,另外一种是Message.obtain(),使用回收但是没有被释放的message对象,减少开销,有点类似Adapter中的ConvertView与ViewHolder,一般使用Message msg = Handler.obtain(),事实上也是调用Message.Obtain().
Handler.class
/** * Returns a new {@link android.os.Message Message} from the global message pool. More efficient than * creating and allocating new instances. The retrieved message has its handler set to this instance (Message.target == this). * If you don't want that facility, just call Message.obtain() instead. */ public final Message obtainMessage() { return Message.obtain(this); }
Message.class
/** * Return a new Message instance from the global pool. Allows us to * avoid allocating new objects in many cases. */ public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; sPoolSize--; return m; } } return new Message(); }
通过recycle回收的Message对象
Message.class
/** * Return a Message instance to the global pool. You MUST NOT touch * the Message after calling this function -- it has effectively been * freed. */ public void recycle() { clearForRecycle(); synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }
二、Handler
Handler用来发送和处理Message,典型的方法有handleMessage(Message),sendMessage(Message)
SendMessage(Message)
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }
sendMessageDelayed(Message msg,long)
public final boolean sendMessageDelayed(Message msg, long delayMillis) { if (delayMillis < 0) { delayMillis = 0; } return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); }
sendMessageAtTime(Message, long)
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实际上就是将msg放入到mQueue;
handleMessage(Message)
/** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }
handleMessage(Message)是一个空方法,需要子类来实现
三、Looper
Looper,消息循环,主要方法loop(),无限循环去mQueue中取消息交给Handler
/** * 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.recycle(); } }其中msg.target就是Handler,而dispatch就是调用了handMessage()
最后将已经出队列的msg回收到pool中备用
四、关系
初始化&发送消息
Handler handler;Looper.prepare();handler = new Handler();Message msg = handler.obtainMessage();msg.what = 1;handler.sendMessage(msg);Looper.loop();
处理消息
class MyHandler extends Handler{@Overridepublic void handleMessage(Message msg) {// TODO Auto-generated method stubswitch (msg.what) {}}}
逐步分析如何实现
Loop.prepare();//实例化Looper,在构造函数中建立一个消息队列MessageQueue,并绑定当前的Thread,所以在哪个线程里实例化Looper,对应的消息队列就依附与那个线程
private Looper() { mQueue = new MessageQueue(); mRun = true; mThread = Thread.currentThread(); }handler = new Handler();//主要是通过Looper获取mQueue,所以实例化Handler之前必须确保当前线程已经绑定了一个Looper,否则如源码所示,抛出异常“can't create handler inside thread that has not called Looper.prepare()”
/** * Default constructor associates this handler with the queue for the * current thread. * * If there isn't one, this handler won't be able to receive messages. */ public Handler() { if (FIND_POTENTIAL_LEAKS) { final Class<? extends Handler> klass = getClass(); if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && (klass.getModifiers() & Modifier.STATIC) == 0) { Log.w(TAG, "The following Handler class should be static or leaks might occur: " + klass.getCanonicalName()); } } mLooper = Looper.myLooper(); if (mLooper == null) { throw new RuntimeException( "Can't create handler inside thread that has not called Looper.prepare()"); } mQueue = mLooper.mQueue; mCallback = null; }
Message msg = handler.obtain();//参照Message部分介绍
msg.what = 1;
handler.sendMessage(msg);//将msg放入队列mQueue
return enqueueMessage(queue, msg, uptimeMillis);
public static void loop() { final MessageQueue queue = me.mQueue; for (;;) { Message msg = queue.next(); // might block msg.target.dispatchMessage(msg); msg.recycle(); } }...
- 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
- Looper、Handler、Message
- AdaBoost人脸检测原理【转摘】
- c#编程之UserControl:用户控件与主界面之间的事件响应
- eclipse maven 安装
- 打开c语言生成exe文件,出现闪退的解决方法
- jquery获取所有选中的checkbook
- Message Handler Looper
- stretchableImageWithLeftCapWidth
- rhel6 ipv6 禁用备忘
- Socket send函数和recv函数详解以及利用select()函数来进行指定时间的阻塞【转】
- 最长上升子序列
- cookie 工作原理
- 【C++ Primer】标准库string类型
- 机器学习算法中文视频教程
- LOWORD与HIWORD,GetEditSel与SetEditSel