感谢师父的帮助和其他大神的帖子。
本文分为两个部分:
1. 线程间通信机制说明。
2. Handler Looper Message MessageQueue类常用方法解读。
继承关系:
线程间通信机制说明:
这四个类组合使用构成了Android线程间通信机制,它们都
继承于android.os类。
在Android中,程序一开始运行就启动了ActivityThread(主线程,也叫UI线程),这个线程用来处理UI相关的任务。为了保证UI线程的高响应速度,规定在开发过程中应尽可能的把耗时操作(I/O等)放在子线程(其他线程)中执行。有些情景是把耗时操作处理完或者正在处理的时候就需要更新UI显示,但如果耗时操作和UI任务不在同一个线程中进行,就需要将子线程中的“任务完成情况”(消息Message)发送到主线程中去,让主线程依照这个消息对UI进行相应的更新等操作。
这个 “将子线程的消息发送到主线程(将一个线程的消息发送到其他线程)” 的过程就是线程间通信。
这个过程是: handler(处理者)调用send/post系列方法把Message(消息)添加到MessageQueue(消息队列)里,然后Looper(轮循者)将MessageQueue中的Message使用handler里面的一个回调方法传给handler的handleMessage()方法对消息进行处理。
在线程间通信整个过程中,send/post(发送消息)方法调用是在子线程(发送消息的线程)完成的, handlerMessage()(处理消息)方法是在主线程(接收消息的线程)调用的。这样就完成了把消息从一个线程发送到另一个线程。
当我们需要跨线程交互的时候,我们的只需要持有交互线程的handler就可以操作交互线程了
但是经常也会使用handler来实现一些代码的动态跳转,更新等任务。
Handler说明:Handler(消息管理者),负责发送消息(send/post)和处理(handleMessage())消息。
每一个线程可以有若干个Handler。
Message说明:Message(消息),封装了一些常量和方法,整个消息传递过程传递的对象就是Message对象。
每一个Handler可以发送若干个Message。
MessageQueue说明:MessageQueue(消息队列),保存消息,handler调用send/post会把消息存到队列里,looper会取出消息。
每一个线程只能有一个MessageQueue。
Looper说明:Looper(轮循者),不断循环检查MessageQueue里面是否有消息,有的话就发送给对应的Handler,Handler再对消息进行处理。
每一个线程只能有一个Looper。
Handler类方法详解
:
构造方法
:
1. 无参构造方法
,
此时创建的Handler默认的Looper是当前线程的looper,在主线程创建Handler时默认Looper是主线程的Looper。
2. (Callback)构造方法
,制定一个回调对象,直接在handlerMessage()方法中写处理消息的逻辑。
3. (Looper)构造方法
,传入一个Looper,代码中这个Looper是主线程Looper。
4. (Looper,Callback)构造方法:
,传入刚才定义的Looper和Callback即可。
常用方法
:
1. 创建消息的方法
:Message对象可以new出来,但是推荐使用Handler.obtain()系列方法创建一个Message。obtain系列方法实际上是调用Message类中的obtain()方法来获取一个空的Message对象然后给其相应参数赋值,源码如下:
,即Message类维护着一个消息池,当前信息对象是sPool,每次从池子中拿出一个Message对象,sPool就指向下一个Message。池子的最大值是50,源码里有写出
,这样的设计可以提高Message的复用率,避免不断创建新的Message占用大量内存空间。
⑴ obtainMessage(); 直接从池子中拿出一个空的Message
⑵ obtainMessage(int what);
⑶ obtainMessage(int what, Object obj);
⑷ obtainMessage(int what, int arg1, int arg2);
⑸ obtainMessage(int what, int arg1, int arg2, Object obj);
Message对象有这些属性(变量),供开发者使用此对象传递信息。一般的,what用来标识消息,这样的好处是处理消息的时候就可以使用switch判断在一个handler中对不同标识的消息进行不同的处理。arg1、arg2、obj这几个都是用来携带信息的,这三个基本可以满足任何信息的携带需求了。
⑹ getPostMessage(Runnable r);
⑺ getPostMessage(Runnable r, Object token);
这两个方法是新添加的方法,在方法内部也会调用obtain无参方法,然后将r和token分别赋给message的callback和obj属性。
2. 发送消息的方法
:
Handler发送消息的实质其实是把消息交给MessageQueue,不管什么方法发送的消息最后都会走这一步
,而这个方法就是MessageQueue类的
给队列增加数据的方法。即发送消息其实是把消息交给MessageQueue。
Post系列:Post系列方法都会调用
这个方法弄出来一个Message对象,把Runnable接口实例作为Message的一个属性,
然后调用Send系列方法发送消息。
注: 以下方法中uptimeMills参数的基准时间是Android.os.SystemClock.uptimeMills(). (PostAtTime/SendMessageAtTime)
⑴ post(Runnable r);
传入一个Runnable接口实例,在这个接口实例的run方法中(主线程)更新UI的逻辑
,也可以写匿名类实现run方法。
⑵ postAtTime(Runnable r, long uptimeMills);
指定一个时间(毫秒值)来发送消息,
,在当前时间的1s后发送消息。
⑶ postAtTime(Runnable r, Object token, long uptimeMills);
指定一个时间(毫秒值)来发送消息,其中token这个参数会在调用getPostMessage方法时被封装成Message的obj属性。
⑷ postDelayed(Runnable r, long delayMills);
延迟一个时间(毫秒值)来发送消息,
,在当前时间的1s后发送消息。
⑸ postAtFrontOfQueue(Runnable t);
发送一个消息,并把消息插到当前消息队列的第一位。
Send系列:
⑹ sendMessage(Message msg);
发送一个消息
⑺ sendEmptyMessage(int what);
发送一个空消息
⑻ sendEmptyMessageDelayed(int what, long delayMills);
延迟一个时间(毫秒值)发送一个空消息
⑼ sendMessageAtTime(int what, long uptimeMills);
指定一个时间(毫秒值)发送一个空消息
⑽ sendMessageDelayed(Message msg, long delayMills);
延迟一个时间(毫秒值)发送一个消息
⑾ sendMessageAtTime(Message msg, long uptimeMills);
指定一个时间(毫秒值)发送一个消息