Android应用程序Handler机制详解
来源:互联网 发布:人工智能原理 编辑:程序博客网 时间:2024/05/18 15:23
之前听朋友讲过handler,之后自己看了下handler的源码(Read The Fucking Source Code。)决定写下关于handler的博客。
1、handler 消息处理器,负责处理消息。
2、Message 消息,包含消息id,被处理的对象。
3、MessageQueue 消息队列,存放Handler发送过来的Message
4、looper 消息泵,不间断的从MessageQueue消息队列中抽取消息。
简单的比喻looper就是水泵,MessageQueue储水的池塘,Message就是水,Handler就是操作的人。
Android应用程序是消息驱动的,并且是全局的消息驱动循环系统,Android通过Looper,handler来实现消息循环机制。
Message:消息对象,MessageQueue中存放的对象,一个MessageQueue中包含多个Message;
MessageQueue:存放Message的数据结构;
Looper:可以看成一个死循环,一直循环去MessageQueue中取Message,每个Looper创建的同时都会创建一个MessageQueue
Handler:消息的处理者;Handler可以通过sendMessage来发送一个消息到MessageQueue中,也可以通过handlerMessage来处理掉一个Message
起初接触这个是子线程更新主线程界面的时候用的,只知道Handler与Message,那我们就从Message与Handler的源码开始看起:
这是我第一次接触到Handler
Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); //这里处理更新界面的操作 } }; new Thread(){ @Override public void run() { super.run(); Message msg = new Message(); msg.obj = 1; handler.sendMessage(msg); } }.start();
先来看Message
Message源码:http://androidxref.com/2.3.7/xref/frameworks/base/core/java/android/os/Message.java
这里说下看源码可以到:http://androidxref.com/看源码
Message源码位置:/frameworks/base/core/java/android/os/Message.java
public final class Message implements Parcelable { public int what; public int arg1; /*package*/ Handler target; /*package*/ Runnable callback; // sometimes we store linked lists of these things /*package*/ Message next;...... private static final Object sPoolSync = new Object(); private static Message sPool; private static int sPoolSize = 0; private static final int MAX_POOL_SIZE = 50; private static boolean gCheckRecycle = true; /** * 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; m.flags = 0; // clear in-use flag sPoolSize--; return m; } } return new Message(); }...... /** * Return a Message instance to the global pool. * <p> * You MUST NOT touch the Message after calling this function because it has * effectively been freed. It is an error to recycle a message that is currently * enqueued or that is in the process of being delivered to a Handler. * </p> */ public void recycle() { if (isInUse()) { if (gCheckRecycle) { throw new IllegalStateException("This message cannot be recycled because it " + "is still in use."); } return; } recycleUnchecked(); }...... /** * Recycles a Message that may be in-use. * Used internally by the MessageQueue and Looper when disposing of queued Messages. */ void recycleUnchecked() { // Mark the message as in use while it remains in the recycled object pool. // Clear out all other details. flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = -1; when = 0; target = null; callback = null; data = null; synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }......}
当看到12行Message next;的注释:有时我们将把这东西存储链表,并看到代码16行private static Message sPool;就会想打Message本身就是链表数据结构;看到19行private static final int MAX_POOL_SIZE = 50;这个链表最大长度是50.接下来我们看27行的obtain()方法,if(sPool != null){//如果sPool中有Message Message m = sPool;//去sPool中获取第一个Message sPool = m.next; //sPool去掉第一Message m.next = null;//把去除的Message的next置空 sPoolSize--;sPool 的长度减去1; return m;获得这个Message}
return new Message();//如果sPool 没有Message就新建一个
看到这里我之前都是直接new Message();这样的话消耗资源比较多。
最好的方法就是 Message msg = Message.obtain();
再看void recycleUnchecked() 方法
void recycleUnchecked() { // Mark the message as in use while it remains in the recycled object pool. // Clear out all other details. flags = FLAG_IN_USE; what = 0; arg1 = 0; arg2 = 0; obj = null; replyTo = null; sendingUid = -1; when = 0; target = null; callback = null; data = null; synchronized (sPoolSync) { if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } } }
看注释就知道使用完Message再把他放回sPool中,并且把所有属性置空。当sPoolSize
好了大致了解了Message,再看看handler.sendMessage(msg);把Message放到了那里
Handler源码位置:/frameworks/base/core/java/android/os/Handler.java
public final boolean sendMessage(Message msg) { return sendMessageDelayed(msg, 0); }
sendMessage最后调用的是
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); } ........ private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) { msg.target = this; if (mAsynchronous) { msg.setAsynchronous(true); } return queue.enqueueMessage(msg, uptimeMillis); }
那么MessageQueue 有是从哪里来的?
public Handler(Callback callback, boolean async) { ..... 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 = callback; mAsynchronous = async; }
看Handler的构造函数mQueue = mLooper.mQueue;是从Looper中得来的,那么Looper是从哪里初始化的呢?
Looper 和MessageQueue其实是在ActivityThread里就初始化了
ActivityThread的源码位置:frameworks/base/core/java/android/app/ActivityThread.java
public final class ActivityThread { public static final void main(String[] args) { ...... Looper.prepareMainLooper(); ...... Looper.loop(); } }
我们再来看看Looper.prepareMainLooper();都干了什么,
Looper源码位置:/frameworks/base/core/java/android/os/Looper.java
public final class Looper { .... private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); } .... 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)); } .... /** * Initialize the current thread as a looper, marking it as an * application's main looper. The main looper for your application * is created by the Android environment, so you should never need * to call this function yourself. See also: {@link #prepare()} */ public static void prepareMainLooper() { prepare(false); synchronized (Looper.class) { if (sMainLooper != null) { throw new IllegalStateException("The main Looper has already been prepared."); } sMainLooper = myLooper(); } } .... public static void loop() { ...... 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); ..... msg.recycleUnchecked(); } } }
看looper源码知道初始化looper的时候同时mQueue = new MessageQueue(quitAllowed);新建了一MessageQueue
在ActivityThread中调用loop();这个方法就是一个死循环一直循环去MessageQueue中拿Message并msg.target.dispatchMessage(msg);,其中msg.target 是handler,这里就是通过handler去处理Message,处理完了 然后通过msg.recycleUnchecked();回收。这个基本上走了一遍,其中有细节东西很多。大家可以去看看源码!
未完待续。。。
- Android应用程序Handler机制详解
- Android Handler机制详解
- Android Handler机制详解
- Android-Handler机制详解
- android中的handler机制详解
- android中handler机制详解
- Android Handler 消息机制详解
- android Handler的机制详解
- android Handler机制源码详解
- Android应用程序消息处理机制Handler分析
- Android中Handler机制的详解
- 【Android】Handler机制源码详解(一)
- 【Android】Handler机制源码详解(二)
- Android Handler异步消息机制详解
- Android源码剖析之-------Handler机制详解
- Android之Handler消息机制详解
- Android中Handler传递消息机制详解
- Android Handler消息处理机制详解
- 修改document.domain会引起的问题
- android studio 没有自动提示
- Strus2_文件的上传与下载
- Solr搜索介绍(Searching)
- Hibernate中一级缓存和二级缓存使用详解
- Android应用程序Handler机制详解
- 文章标题
- 接口和抽象类的区别
- 端口被占用
- 针对苹果最新审核要求为应用兼容IPv6
- GridView控件---应用图标的显示
- RecyclerView嵌套RecyclerView
- SQLServer 查看依赖关系
- oracle的io优化--db_writer_processes & dbwr_io_slaves对比