您的位置:首页 > 产品设计 > UI/UE

谈谈我对Android中的消息机制的理解之Handler,Looper和MessageQueue的解释

2015-06-20 04:19 701 查看
Handler的作用是:发送Message和处理Message,handler发送的Message其实就是发送给自己的对象进行处理,所以谁发送就是谁处理,但是这个绝对有意义,以为这样我们就可以通过Handler将消息的处理从一个线程转到另一个线程了,这个Message几经转手之后,处理它的对象虽然是同一个,但是处理它的线程就变了,变成了创建Handler对象的线程,而不是产生Message对象的线程(当然,这个两个线程可能是一个,但是这样使用handler就是第二个目的了),使用handler的第二个目的是可以是一个Message的处理在未来特定的时间发生,就是延迟消息的处理,比如handler的postDelayed()或者sendMessageDelayed()或sendMessageAtTime()方法。

Looper的作用是关联一个MessageQueue,并且对这个MessageQueue进行轮询,调用它的loop()方法。Looper对象的创建需要调用它的prepare()静态方法创建,不能new。哪个线程创建了Looper,哪个线程就负责调用Looper的loop()方法进行Message的轮询。

MessageQueue的作用是维护一个消息队列,提供给Looper进行轮询,Looper中包含了MessageQueue的引用,创建了Looper对象就创建了一个与之对应的MessageQueue对象,这个MessageQueue对象也是本地的message queue,因为创建它的时候调用了native方法。

Handler和Looper和MessageQueue之间的关系:Handler对象中既有Looper对象的引用也有MessageQueue对象的引用,其中MessageQueue是通过它的Looper对象的一个mQueue属性获取的,而Looper的对象是创建Handler的线程创建的(创建Looper对象需要调用它的静态方法prepare()创建,不能直接new出来),所以我们可以说Handler中的MessageQueue是属于创建这个Handler的线程的,而且实际上也是由这个线程通过它创建的Looper对象的loop()方法对这个MessageQueue进行轮询的。

Looper的对象是通过当前创建Handler的线程创建的,并且要保证这个线程要去调用Looper对象的loop()方法进行Message的轮询(在loop()内部会调用一些native的方法完成本地的消息轮询),如果要退出轮询,可以调用Looper对象的quit()方法。UI线程(主线程)已经帮我们做好了这一切,所以,如果我们在主线程中创建Handler,那么就是由主线程自动帮我们去轮询我们的MessageQueue,所以我们在子线程中调用Handler对象的post(),sendMessage(),才能在主线程(UI线程)中处理我们的Message,而且才能在主线程(UI线程)中更新我们的UI。

其实post(),postDelayed(), sendMessage(), sendMessageDelayed() 这四个方法本质都是调用的sendMessageAtTime()这个方法,只是post对runnable对象进行了包装,包装成了Message对象,而这个Message对象的callback就是runnable,最后我们在选择Message处理方法的时候,优先看这个Message对象有没有callback对象,如果有,就调用这个callback对象,然后再看整个handler对象有没有callback对象,如果有,就调用这个callback对象的handleMessage()方法处理Message对象,如果没有则调用handler对象本身的handleMessage方法处理Message,所以Message的处理是有优先级的。

Handler,Looper和MessageQueue的包含关系

Handler包含了Looper,也包含了Looper的MessageQueue;

Looper包含了MessageQueue,

所以Looper属于Handler,由创建Handler的线程创建和使用,MessageQueue属于Looper,通过创建Handler的线程调用Looper的loop()方法进行轮询。

当我们将Handler对象在主线程(UI线程)中创建的时候,Handler对象会关联一个Looper对象,这个Looper对象不是我们创建的,是早就由Activity中的ActivityThread这个类在main函数中创建好的(整个Android应用的入口函数就是这个main函数),如下:

public static void main(String[] args) {
SamplingProfilerIntegration.start();

// CloseGuard defaults to true and can be quite spammy.  We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);

Environment.initForCurrentUser();

// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());

Security.addProvider(new AndroidKeyStoreProvider());

// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);

Process.setArgV0("<pre-initialized>");

Looper.prepareMainLooper();

ActivityThread thread = new ActivityThread();
thread.attach(false);

if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}

if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}

Looper.loop();

throw new RuntimeException("Main thread loop unexpectedly exited");
}


从上面的代码我们可以看见Looper对象是通过Looper.prepareMainLooper()来创建的,而调用loop()开始消息的轮询是在最后:Looper.loop()。通过源码我们可以看见loop()内部是一个for(;;){}的死循环,这个就是整个应用程序的main thread loop。我们开发window应用的时候都知道这个应用就是一个大的死循环,称为main thread loop,而Android应用的main thread loop就在这里。这下我们就知道我们的消息究竟是怎样被轮询和处理了的吧!找到主循环,一切都迎刃而解了!

总结:Handler负责发送消息和处理消息;Looper负责接收消息和轮询消息,并且将消息转发给Handler自己,由Handler自己在不同的线程中处理消息;MessageQueue就是一个消息的容器,Looper内部包含了MessageQueue对象的引用,就是通过这个容器(其实就是一个以linked list形式保存Message对象的数据结构),Looper才能完成对消息的轮询(通过loop()方法)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: