Handler机制解析
Posted nangongyibin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Handler机制解析相关的知识,希望对你有一定的参考价值。
Hanlder机制用于线程间通信,通常用于子线程给主线程发送消息更新UI
Handler
Message的主要处理者,用于发送消息,接收处理消息
Message
消息,线程间通信的数据单元
MessageQueue
消息队列,用于存放消息,取出消息
Looper
循环器,Message和Handler的桥梁,循环取出MessageQueue的消息发送Handler
需要注意几点:
在创建Handler之前,需要调用Looper.prepare()方法,之所以平常使用未调用过,是因为android在程序启动时帮我们创建好了,具体代码在activityThread中的main()方法中,
public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start(); CloseGuard.setEnabled(false); Environment.initForCurrentUser(); EventLogger.setReporter(new EventLoggingReporter()); final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper();//在此调用的Looper.prepare() ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }
因此我们在子线程使用Handler的时候,需要调用Looper.prepare()方法
class LooperThread extends Thread { public Handler mHandler; public void run() { Looper.prepare(); mHandler = new Handler() { public void handleMessage(Message msg) { // process incoming messages here } }; Looper.loop(); } }
调用Looper.prepare()方法后只能确保在创建Handler的时候不报错,如果不调用Looper.loop()方法,则没有任何效果,同样,android在程序启动时,已经为我们做好了这一步
public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start(); CloseGuard.setEnabled(false); Environment.initForCurrentUser(); EventLogger.setReporter(new EventLoggingReporter()); final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Process.setArgV0("<pre-initialized>"); Looper.prepareMainLooper();//在此调用的Looper.prepare() ActivityThread thread = new ActivityThread(); thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); Looper.loop();//在此调用的Looper.loop() throw new RuntimeException("Main thread loop unexpectedly exited"); }
Handler的工作原理
当我们启动程序的时候,android自动在ActivityThread中帮我们创建了Looper.prepare()方法,创建了Looper对象.
在调用Looper.prepare()方法时,会创建Looper对象,当前线程会将Looper的对象保存,并且在Looper构造方法中,创建MessageQueue对象,也就是说一个Looper一个MessageQueue
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)); } private Looper(boolean quitAllowed) { mQueue = new MessageQueue(quitAllowed); mThread = Thread.currentThread(); }
Handler调用postMessage之类的方法,最后都会调用sendMessageAtTime()方法,其中有queue.equeueMessage(msg)方法,实际就是消息入列逻辑
public boolean sendMessageAtTime(Message msg, long uptimeMillis){ boolean sent = false; MessageQueue queue = mQueue; if (queue != null) { msg.target = this; //该方法为将消息添加到MessageQueue sent = queue.enqueueMessage(msg, uptimeMillis); } else { RuntimeException e = new RuntimeException( this + " sendMessageAtTime() called with no mQueue"); Log.w("Looper", e.getMessage(), e); } return sent; } final boolean enqueueMessage(Message msg, long when) { if (msg.when != 0) { throw new AndroidRuntimeException(msg + " This message is already in use."); } if (msg.target == null && !mQuitAllowed) { throw new RuntimeException("Main thread not allowed to quit"); } synchronized (this) { 10 9 if (mQuiting) { RuntimeException e = new RuntimeException(msg.target + " sending message to a Handler on a dead thread"); Log.w("MessageQueue", e.getMessage(), e); return false; } else if (msg.target == null) { mQuiting = true; } //将消息的时间传进来赋给Message msg.when = when; Message p = mMessages; 0 if (p == null || when == 0 || when < p.when) { msg.next = p; 1 //将要取出的消息 mMessages = msg; 0 this.notify(); } else { Message prev = null; while (p != null && p.when <= when) { prev = p; p = p.next; } msg.next = prev.next; prev.next = msg; this.notify(); } } return true; }
由上面我们可以得知,其实MessageQueue并没有用集合将消息存储起来,而是mMessages对象表示当前待处理的消息,所谓的加入队列其实就是将所有的消息按时间进行排序,具体的操作就是根据Message的时间,去调用msg.next。
从消息取出消息队列是通过Looper.loop(),实际上是一个死循环,不断调用MessageQueue.next方法,他其中的操作就是判断当前是否有需要处理的消息,如果有,则取出来,将下个消息成为mMessages,否则就进入阻塞状态,一直等待新消息的加入。
public static final void loop() { Looper me = myLooper(); MessageQueue queue = me.mQueue; while (true) { Message msg = queue.next(); // might block if (msg != null) { if (msg.target == null) { return; } if (me.mLogging!= null) me.mLogging.println( ">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what ); msg.target.dispatchMessage(msg); if (me.mLogging!= null) me.mLogging.println( "<<<<< Finished to " + msg.target + " " + msg.callback); msg.recycle(); } } }
在Looper.loop()方法中找到将要处理的消息后,会调用msg.target.disPatcheMessage()方法,msg.target就是Handler.也就是调用了Handler.disPatchMessage()方法,在这个方法中,会判断mCallBack是否为空,如果不为空调用callback,如果为空,则调用了handlerMessage()方法,至此整个消息处理完成
public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } handleMessage(msg); } }
对于上条的mCallBack,是因为在创建Handler对象的时候可以传入一个CallBack对象,如果return true,下面的handlermessage就不会收到消息,反正则能收到消息
private Handler mHandler = new Handler(new Handler.Callback() { @Override public boolean handleMessage(Message msg) { //返回为true则下面的handlerMessage不能收到消息 //返回false则下面的hanlderMessage能够收到消息 return false; } }){ @Override public void handleMessage(Message msg) { super.handleMessage(msg); } };
以上是关于Handler机制解析的主要内容,如果未能解决你的问题,请参考以下文章