1.handler作用:
1)传递消息Message
- //2种创建消息方法
- //1.通过handler实例获取
- Handler handler = new Handler();
- Message message=handler.obtainMessage();
- //2.通过Message获取
- Message message=Message.obtain();
- //源码中第一种获取方式其实也是内部调用了第二种:
- public final Message obtainMessage(){
- return Message.obtain(this);
- }
不建议直接new Message,Message内部保存了一个缓存的消息池,我们可以用obtain从缓存池获得一个消息,Message使用完后系统会调用recycle回收,如果自己new很多Message,每次使用完后系统放入缓存池,会占用很多内存的。
- //传递的数据
- Bundle bundle = new Bundle();
- bundle.putString("msg", "传递我这个消息");
- //发送数据
- Message message = Message.obtain();
- message.setData(bundle); //message.obj=bundle 传值也行
- message.what = 0x11;
- handler.sendMessage(message);
- //数据的接收
- final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- if (msg.what == 0x11) {
- Bundle bundle = msg.getData();
- String date = bundle.getString("msg");
- }
- }
- };
2)子线程通知主线程更新ui
- //创建handler
- final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- if (msg.what == 0x11) {
- //更新ui
- ......
- }
- }
- };
- new Thread(new Runnable() {
- @Override
- public void run() {
- //FIXME 这里直接更新ui是不行的
- //还有其他更新ui方式,runOnUiThread()等
- message.what = 0x11;
- handler.sendMessage(message);
- }
- }).start();
2.常用api
- //消息
- Message message = Message.obtain();
- //发送消息
- new Handler().sendMessage(message);
- //延时1s发送消息
- new Handler().sendMessageDelayed(message, 1000);
- //发送带标记的消息(内部创建了message,并设置msg.what = 0x1)
- new Handler().sendEmptyMessage(0x1);
- //延时1s发送带标记的消息
- new Handler().sendEmptyMessageDelayed(0x1, 1000);
- //延时1秒发送消息(第二个参数为:相对系统开机时间的绝对时间,而SystemClock.uptimeMillis()是当前开机时间)
- new Handler().sendMessageAtTime(message, SystemClock.uptimeMillis() + 1000);
- //避免内存泄露的方法:
- //移除标记为0x1的消息
- new Handler().removeMessages(0x1);
- //移除回调的消息
- new Handler().removeCallbacks(Runnable);
- //移除回调和所有message
- new Handler().removeCallbacksAndMessages(null);
3.handler使用避免内存泄露
1)handler怎么使用会产生内存泄露?
- public class MainActivity extends AppCompatActivity {
- final Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- ......
- }
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //activity被执行时,被延迟的这个消息存于主线程消息队列中1分钟,
- //此消息包含handler引用,而handler由匿名内部类创建,持有activity引用,
- //activity便不能正常销毁,从而泄露
- handler.postDelayed(new Runnable() {
- @Override
- public void run() {
- ......
- }
- }, 1000 * 60);
- }
- }
2)如何避免handler的内存泄露?
- public class MainActivity extends AppCompatActivity {
- //创建静态内部类
- private static class MyHandler extends Handler{
- //持有弱引用MainActivity,GC回收时会被回收掉.
- private final WeakReference<MainActivity> mAct;
- public MyHandler(MainActivity mainActivity){
- mAct =new WeakReference<MainActivity>(mainActivity);
- }
- @Override
- public void handleMessage(Message msg) {
- MainActivity mainAct=mAct.get();
- super.handleMessage(msg);
- if(mainAct!=null){
- //执行业务逻辑
- }
- }
- }
- private static final Runnable myRunnable = new Runnable() {
- @Override
- public void run() {
- //执行我们的业务逻辑
- }
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- MyHandler myHandler=new MyHandler(this);
- //延迟5分钟后发送
- myHandler.postDelayed(myRunnable, 1000 * 60 * 5);
- }
- }
3) 雷区
a)Handler.post(Runnable)其实就是生成一个what为0的Message,调用
myHandler.removeMessages(0);
会使runnable任务从消息队列中清除。
详细解释:https://www.cnblogs.com/coding-way/p/5110125.html(转)
b) 子线程直接创建Handler,抛异常Can't create handler inside thread that has not called Looper.prepare()
原因是非主线程没有loop对象,所以要调用Looper.prepare()方法,而且如果主线程给子线程发送消息,还要调用一个Looper.loop()的方法(此方法保证消息队列中的消息被不停的拿出,并被处理)
- class MyThread extends Thread{
- @Override
- public void run() {
- super.run();
- Looper.prepare();
- Handler handler = new Handler() {
- @Override
- public void handleMessage(Message msg) {
- super.handleMessage(msg);
- //处理消息
- }
- };
- Looper.loop();
- }
- }
c)activity如被finish,但是handler刚好还在处理消息,如果需要用的资源已被释放,则会出现空指针异常。
所以在ondestory中去remove掉我们要处理的事件,还是有必要的。不想处理就直接try catch或者判空。
d)有时候你会发现removeCallbacks会失效,不能从消息队列中移除。
出现这情况是activity切入后台,再回到前台,此时的runnable由于被重定义,就会和原先的runnable并非同一个对象。所以这么做,加上static即可
- static Handler handler = new Handler();
- static Runnable myRunnable = new Runnable() {
- @Override
- public void run() {
- //执行我们的业务逻辑
- }
- };
这样,因为静态变量在内存中只有一个拷贝,保证runnable始终是同一个对象。
4.handlerThread
1) handlerThread是什么?
(题外话:异步存在形式有thread,handlerThead,asyncTask,线程池,intentService)
handlerThread继承thread,不过内部比普通线程多了一个Looper
- //内部Looper.prepare()
- @Override
- public void run() {
- mTid = Process.myTid();
- Looper.prepare();
- synchronized (this) {
- mLooper = Looper.myLooper();
- notifyAll();
- }
- Process.setThreadPriority(mPriority);
- onLooperPrepared();
- Looper.loop();
- mTid = -1;
- }
2)HandlerThread使用及销毁
- public class MainActivity extends AppCompatActivity {
- private HandlerThread thread;
- static Handler mHandler;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- //创建一个HandlerThread并启动它
- thread = new HandlerThread("MyHandlerThread");
- thread.start();
- //使用HandlerThread的looper对象创建Handler
- mHandler = new Handler(thread.getLooper(), new Handler.Callback() {
- @Override
- public boolean handleMessage(Message msg) {
- //这个方法是运行在 handler-thread 线程中的,可以执行耗时操作,因此不能更新ui,要注意
- if (msg.what == 0x1) {
- try {
- Thread.sleep(3000);
- Log.e("测试: ", "执行了3s的耗时操作");
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- //这个方法是运行在 handler-thread 线程中的,可以执行耗时操作,因此不能更新ui,要注意
- // ((Button) MainActivity.this.findViewById(R.id.button)).setText("hello");
- }
- return false;
- }
- });
- //停止handlerthread接收事件
- findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- thread.quit();
- }
- });
- //运行
- mHandler.sendEmptyMessage(0x1);
- }
- }
上面demo中,只要调用了
mHandler.sendEmptyMessage(0x1);
就会开始执行任务
几个地方要注意:
a.handleMessage()可以做耗时操作,但是不能更新ui
b.如果不手动的调用HandlerThread.quit()或者HandlerThread..quitSafely()方法,HandlerThread会将持续的接收新的任务事件。
c.只有handleMessage()方法执行完,这轮的任务才算完成,HandlerThread才会去执行下一个任务。而且在此次执行时,即使手动的去调用quit()方法,HandlerThread的此次任务也不会停止。但是,会停止下轮任务的接收。
- 举例:
- //耗时任务换成这个,点击按钮执行quit()方法,发现此次任务依旧执行
- for (int i = 0; i < 99999999; i++) {
- Log.e("测试: ", "输出" +i);
- }
d.HandlerThread的2种停止接收事件的方法。
第一个就是quit(),实际上执行了MessageQueue中的removeAllMessagesLocked方法,该方法的作用是把MessageQueue消息池中所有的消息全部清空,无论是延迟消息(带Delayed的)还是非延迟消息。
第二个就是quitSafely(),执行了MessageQueue中的removeAllFutureMessagesLocked方法,该方法只会清空MessageQueue消息池中所有的延迟消息,并将消息池中所有的非延迟消息派发出去让Handler去处理,quitSafely相比于quit方法安全之处在于清空消息之前会派发所有的非延迟消息。
- MessageQueue中源码:
- void quit(boolean safe) {
- if (!mQuitAllowed) {
- throw new IllegalStateException("Main thread not allowed to quit.");
- }
- synchronized (this) {
- if (mQuitting) {
- return;
- }
- mQuitting = true;
- if (safe) {
- removeAllFutureMessagesLocked();
- } else {
- removeAllMessagesLocked();
- }
- // We can assume mPtr != 0 because mQuitting was previously false.
- nativeWake(mPtr);
- }
- }
- 举例:
- //quit方法后,即使发送新事件,也不会被接收
- findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View v) {
- thread.quit();
- //发送新事件
- mHandler.sendEmptyMessage(0x1);
- }
- );
e.即使多次执行mHandler.sendEmptyMessage(0x1),任务队列中的任务依然只能一个一个的被处理。上一任务结束,开始执行下一个。
- 日志显示:输出0-99的任务结束,才执行下个输出0-99的任务
- 08-09 20:17:05.552 12618-12762/com.bihucj.mcandroid E/测试:: 输出95
- 08-09 20:17:05.552 12618-12762/com.bihucj.mcandroid E/测试:: 输出96
- 08-09 20:17:05.552 12618-12762/com.bihucj.mcandroid E/测试:: 输出97
- 08-09 20:17:05.552 12618-12762/com.bihucj.mcandroid E/测试:: 输出98
- 08-09 20:17:05.552 12618-12762/com.bihucj.mcandroid E/测试:: 输出99
- 08-09 20:17:05.718 12618-12762/com.bihucj.mcandroid E/测试:: 输出0
- 08-09 20:17:05.718 12618-12762/com.bihucj.mcandroid E/测试:: 输出1
- 08-09 20:17:05.719 12618-12762/com.bihucj.mcandroid E/测试:: 输出2
- 08-09 20:17:05.719 12618-12762/com.bihucj.mcandroid E/测试:: 输出3
- 08-09 20:17:05.719 12618-12762/com.bihucj.mcandroid E/测试:: 输出4
- 08-09 20:17:05.719 12618-12762/com.bihucj.mcandroid E/测试:: 输出5
5.源码解析
说到源码,主要还是几个关键词。分别为Message,Looper,MessageQueue,Handler。还有Thread
先说Looper,MessageQueue,Handler3者关联的思路:
主线程-->prepareMainLooper()(内部调用prepare() ,去实例化Looper,Looper实例化同时创建了messagequeue,11对应关系)-->主线程中的handler获取当前线程的Looper-->3者关联
- 插播主线程ActivityThread:
- public static void main(String[] args) {
- ......
- Looper.prepareMainLooper();
- ......
- //区别:子线程是创建handler;
- //主线程是通过getHandler()获取内部类实例
- if(sMainThreadHandler==null){
- sMainThreadHandler=thread.getHandler();
- }
- ......
- }
- private class H extends Handler{
- ......
- }
子线程-->直接通过Looper.prepare()去实例化Looper,Looper实例化同时创建了messagequeue(11对应关系) -->实例化Handler同时获取当前子线程的Looper-->3者关联
1)Message消息
- public final class Message implements Parcelable {
- //用户定义的消息代码,以便接收者能够识别
- public int what;
- //arg1和arg2是使用成本较低的替代品-也可以用来存储int值
- public int arg1;
- public int arg2;
- //存放任意类型的对象
- public Object obj;
- //消息触发时间
- long when;
- //消息携带内容
- Bundle data;
- //消息响应方
- Handler target;
- //消息管理器,会关联到一个handler
- public Messanger replyTo;
- //回调方法
- Runnable callback;
- //消息存储的链表。这样sPool就成为了一个Messages的缓存链表。
- Message next;
- //消息池
- private static Message sPool;
- //消息池的默认大小
- private static final int MAX_POOL_SIZE = 50;
- //从消息池中获取消息
- public static Message obtain() {
- synchronized (sPoolSync) {
- if (sPool != null) {
- Message m = sPool; //从sPool的表头拿出Message
- sPool = m.next; //将消息池的表头指向下一个Message
- m.next = null; //将取出消息的链表断开
- m.flags = 0; // 清除flag----flag标记判断此消息是否正被使用(下方isInUse方法)
- sPoolSize--; //消息池可用大小进行减1
- return m;
- }
- }
- return new Message(); //消息池为空-直接创建Message
- }
- //通过标记判断消息是否正被使用
- boolean isInUse() {
- return ((flags & FLAG_IN_USE) == FLAG_IN_USE);
- }
- //5.0后为true,之前为false.
- private static boolean gCheckRecycle = true;
- public void recycle() {
- if (isInUse()) {
- if (gCheckRecycle) {
- throw new IllegalStateException("This message cannot be recycled because it is still in use.");
- }
- return;
- }
- recycleUnchecked(); //消息没在使用,回收
- }
- //对于不再使用的消息,加入到消息池
- void recycleUnchecked() {
- //将消息标示位置为IN_USE,并清空消息所有的参数。
- 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; //当消息池没有满时,将Message加入消息池
- sPoolSize++; //消息池可用大小加1
- }
- }
- }
2)Looper
https://blog.csdn.net/woshiluoye9/article/details/72544764 (转)
- 插播ThreadLocal:
- ThreadLocal是线程的局部变量, 是每一个线程所单独持有的,其他线程不能对其进行访问。
主线程和子线程中的Looper的初始化
- public final class Looper {
- //内部消息队列MessageQueue
- final MessageQueue mQueue;
- //Looper所在的线程
- final Thread mThread;
- //Looper的变量存储
- static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
- //主looper
- private static Looper sMainLooper;
- //私有构造方法,不能通过New实例化。
- private Looper(boolean quitAllowed) {
- mQueue = new MessageQueue(quitAllowed);//创建与其绑定的消息队列MessageQueue
- mThread = Thread.currentThread(); //绑定当前线程
- }
- //子线程的调用----->最终通过prepare(boolean)实例化Looper
- public static void prepare() {
- prepare(true);
- }
- //主线程的调用----->最终通过prepare(boolean)实例化Looper
- public static void prepareMainLooper() {
- prepare(false);
- synchronized (Looper.class) {
- if (sMainLooper != null) {
- throw new IllegalStateException("The main Looper has already been prepared.");
- }
- sMainLooper = myLooper();//存储区中looper作为主looper
- }
- }
- public static @Nullable Looper myLooper() {
- return sThreadLocal.get();
- }
- //quitAllowed代表是否允许退出,主线程调用为不允许退出,子线程为可退出
- private static void prepare(boolean quitAllowed) {
- if (sThreadLocal.get() != null) {
- //看出一个线程只能存在一个Looper-->则调用二次Looper.prepare抛出异常
- throw new RuntimeException("Only one Looper may be created per thread");
- }
- sThreadLocal.set(new Looper(quitAllowed));//Looper的变量存储+实例化Looper
- }
Loop()方法,循环取出messagequeue消息队列中的消息,并分发出去。再把分发后的Message回收到消息池,以便重复利用。
- public static void loop() {
- final Looper me = myLooper(); //从存储区拿出looper
- if (me == null) {
- throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
- }
- final MessageQueue queue = me.mQueue; //获取Looper对象中的消息队列
- ......
- //进入loop的主循环方法
- for (;;) {
- Message msg = queue.next(); //可能会阻塞
- if (msg == null) { //没有消息,则退出循环
- return;
- }
- ......
- //target是handler,此处用于分发Message
- msg.target.dispatchMessage(msg);
- ......
- msg.recycleUnchecked(); //将Message放入消息池
- }
- }
Looper中的quit方法-->调用的还是messageQueue中的quit()
- public void quit() {
- mQueue.quit(false);
- }
3) MessageQueue消息队列
a)主要参数和构造方法
- public final class MessageQueue {
- //供native代码使用
- @SuppressWarnings("unused")
- private long mPtr;
- //交给native层来处理的核心方法
- private native static long nativeInit();
- private native static void nativeDestroy(long ptr);
- private native void nativePollOnce(long ptr, int timeoutMillis); //阻塞操作
- private native static void nativeWake(long ptr);
- private native static boolean nativeIsPolling(long ptr);
- private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
- Message mMessages;
- //消息队列是否可以退出
- private final boolean mQuitAllowed;
- //构造方法
- MessageQueue(boolean quitAllowed) {
- mQuitAllowed = quitAllowed;
- mPtr = nativeInit(); //通过native方法初始化消息队列,其中mPtr是供native代码使用
- }
b)核心的next()方法
- //不停提取下一条message
- Message next() {
- final long ptr = mPtr;
- //判断是否退出消息循环
- if (ptr == 0) {
- return null;
- }
- int pendingIdleHandlerCount = -1;
- //代表下一个消息到来前,还需要等待的时长
- int nextPollTimeoutMillis = 0;
- for (;;) {
- if (nextPollTimeoutMillis != 0) {
- Binder.flushPendingCommands();
- }
- //native层阻塞cpu。如果被阻塞,唤醒事件队列
- nativePollOnce(ptr, nextPollTimeoutMillis);
- synchronized (this) {
- final long now = SystemClock.uptimeMillis();
- Message prevMsg = null;
- Message msg = mMessages;
- //如果当前消息是异步消息,都将赋值给prevMsg,过滤掉,直到取到了非异步消息
- if (msg != null && msg.target == null) {
- do {
- prevMsg = msg;
- msg = msg.next;
- } while (msg != null && !msg.isAsynchronous());
- }
- //获取到了非异步消息
- if (msg != null) {
- //任务执行时间大于现在的时间
- if (now < msg.when) {
- //设置下一次轮询的超时时长
- nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
- } else {
- mBlocked = false;//指定为非阻塞任务
- if (prevMsg != null) {
- prevMsg.next = msg.next;
- } else {
- mMessages = msg.next;
- }
- msg.next = null;
- //设置消息的使用状态,即flags |= FLAG_IN_USE
- msg.markInUse();
- return msg; //成功地获取MessageQueue中的下一条即将要执行的消息
- }
- } else {
- //表示消息队列中无消息,会一直等待下去
- nextPollTimeoutMillis = -1;
- }
- ......
- //IdleHandler为发现线程何时阻塞的回调接口
- for (int i = 0; i < pendingIdleHandlerCount; i++) {
- final IdleHandler idler = mPendingIdleHandlers[i];
- mPendingIdleHandlers[i] = null; //去除handler引用
- boolean keep = false;
- //queueIdle返回true会被空闲的处理器处理,false就会被移走
- try {
- keep = idler.queueIdle(); //idle时执行的方法
- } catch (Throwable t) {
- Log.wtf(TAG, "IdleHandler threw exception", t);
- }
- if (!keep) {
- synchronized (this) {
- mIdleHandlers.remove(idler); //被移走
- }
- }
- }
- //重置idle handler个数为0,保证不会再次重复运行
- pendingIdleHandlerCount = 0;
- nextPollTimeoutMillis = 0;
- }
- }
next()方法中,做了异步Message消息的判断,特殊的是这个Message没有设置target,即msg.target为null。
c)核心的enqueueMessage()方法
- boolean enqueueMessage(Message msg, long when) {
- // 每一个普通Message必须有一个target-handler
- if (msg.target == null) {
- throw new IllegalArgumentException("Message must have a target.");
- }
- //已在使用状态
- if (msg.isInUse()) {
- throw new IllegalStateException(msg + " This message is already in use.");
- }
- synchronized (this) {
- //消息在退出状态->被回收到消息池
- if (mQuitting) {
- msg.recycle();
- return false;
- }
- //标记使用状态,记录执行时间
- msg.markInUse();
- msg.when = when;
- Message p = mMessages;
- boolean needWake;
- //p为null代表MessageQueue没有消息或者msg的触发时间是队列中最早的
- if (p == null || when == 0 || when < p.when) {
- msg.next = p;
- mMessages = msg;
- needWake = mBlocked; //当阻塞时需要唤醒
- } else {
- //将消息按时间顺序插入到MessageQueue。
- needWake = mBlocked && p.target == null && msg.isAsynchronous();
- Message prev;
- for (;;) {
- prev = p;
- p = p.next;
- if (p == null || when < p.when) {
- break;
- }
- if (needWake && p.isAsynchronous()) {
- needWake = false;
- }
- }
- msg.next = p;
- prev.next = msg;
- }
- if (needWake) {
- nativeWake(mPtr);
- }
- }
- return true;
- }
队列中的Message触发时间是有先后顺序的。当消息加入消息队列时,会从队列头开始遍历,直到找到消息应该插入的合适位置,以保证所有消息的时间顺序(内部遍历队列中Message,找到when比当前Message的when大的Message,将Message插入到该Message之前,如果没找到则将Message插入到队列最后)。一般是当前队列为空的情况下,next那边会进入睡眠,需要的时候MessageQueue这边会唤醒next方法。
d)removeMessages()和removeCallbacksAndMessages()方法
- void removeMessages(Handler h, int what, Object object) {
- if (h == null) {
- return;
- }
- synchronized (this) {
- Message p = mMessages;
- //从消息队列的头部开始,移除所有符合条件的消息
- while (p != null && p.target == h && p.what == what
- && (object == null || p.obj == object)) {
- Message n = p.next;
- mMessages = n;
- p.recycleUnchecked();
- p = n;
- }
- //移除剩余的符合要求的消息
- while (p != null) {
- Message n = p.next;
- if (n != null) {
- if (n.target == h && n.what == what
- && (object == null || n.obj == object)) {
- Message nn = n.next;
- n.recycleUnchecked();
- p.next = nn;
- continue;
- }
- }
- p = n;
- }
- }
- }
- void removeCallbacksAndMessages(Handler h, Object object) {
- if (h == null) {
- return;
- }
- synchronized (this) {
- Message p = mMessages;
- while (p != null && p.target == h
- && (object == null || p.obj == object)) {
- Message n = p.next;
- mMessages = n;
- p.recycleUnchecked();
- p = n;
- }
- while (p != null) {
- Message n = p.next;
- if (n != null) {
- if (n.target == h && (object == null || n.obj == object)) {
- Message nn = n.next;
- n.recycleUnchecked();
- p.next = nn;
- continue;
- }
- }
- p = n;
- }
- }
- }
4)Handler
a)主要参数和构造方法
- public class Handler {
- final Looper mLooper;
- final MessageQueue mQueue;
- final Callback mCallback; //回调
- final boolean mAsynchronous; //是否异步消息
- IMessenger mMessenger;
- public interface Callback {
- //如果不需要进一步的处理,则返回True
- public boolean handleMessage(Message msg);
- }
- //有参构造
- public Handler(Looper looper) {
- this(looper, null, false);
- }
- //有参构造
- public Handler(Looper looper, Callback callback, boolean async) {
- mLooper = looper;
- mQueue = looper.mQueue;
- mCallback = callback;
- mAsynchronous = async;
- }
- public Handler(Callback callback, boolean async) {
- //匿名类、内部类或本地类都必须申明为static,否则会警告可能出现内存泄露
- 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());
- }
- }
- //从Looper类中的(ThreadLocal)获取Looper对象
- mLooper = Looper.myLooper();
- if (mLooper == null) {
- throw new RuntimeException("");
- }
- mQueue = mLooper.mQueue; //Looper取出消息队列
- mCallback = callback; //回调
- mAsynchronous = async; //设置消息是否为异步处理方式
- }
b)消息的发送:
- 1.post--->调用sendMessageDelayed
- public final boolean post(Runnable r){
- return sendMessageDelayed(getPostMessage(r), 0);
- }
- 2.postAtTime--->调用sendMessageAtTime
- public final boolean postAtTime(Runnable r, long uptimeMillis){
- return sendMessageAtTime(getPostMessage(r), uptimeMillis);
- }
- 3.postAtTime--->调用sendMessageAtTime
- public final boolean postAtTime(Runnable r, Object token, long uptimeMillis){
- return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
- }
- 4.postDelayed--->调用sendMessageDelayed
- public final boolean postDelayed(Runnable r, long delayMillis){
- return sendMessageDelayed(getPostMessage(r), delayMillis);
- }
- 5.postAtFrontOfQueue--->调用sendMessageAtFrontOfQueue
- public final boolean postAtFrontOfQueue(Runnable r){
- return sendMessageAtFrontOfQueue(getPostMessage(r));
- }
- 6.sendMessage--->调用sendMessageDelayed
- public final boolean sendMessage(Message msg){
- return sendMessageDelayed(msg, 0);
- }
- 7.sendEmptyMessage--->调用sendEmptyMessageDelayed
- public final boolean sendEmptyMessage(int what){
- return sendEmptyMessageDelayed(what, 0);
- }
- 8.sendEmptyMessageDelayed--->调用sendMessageDelayed
- public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
- Message msg = Message.obtain();
- msg.what = what;
- return sendMessageDelayed(msg, delayMillis);
- }
- 9.sendEmptyMessageAtTime--->调用sendMessageAtTime
- public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
- Message msg = Message.obtain();
- msg.what = what;
- return sendMessageAtTime(msg, uptimeMillis);
- }
- 10.sendMessageDelayed--->调用sendMessageAtTime
- public final boolean sendMessageDelayed(Message msg, long delayMillis){
- if (delayMillis < 0) {
- delayMillis = 0;
- }
- return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
- }
- 11.sendMessageAtTime--->调用enqueueMessage
- 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);
- }
- 12.sendMessageAtFrontOfQueue--->调用enqueueMessage
- //FIXME 该方法通过设置消息的触发时间为0,从而使Message加入到消息队列的队头
- public final boolean sendMessageAtFrontOfQueue(Message msg) {
- 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, 0);
- }
- 13.enqueueMessage调用MessageQueue中的enqueueMessage
- private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
- msg.target = this;
- if (mAsynchronous) {
- msg.setAsynchronous(true);
- }
- //uptimeMillis为系统当前的运行时间
- return queue.enqueueMessage(msg, uptimeMillis);
- }
- if (mAsynchronous) {
- msg.setAsynchronous(true);
- }
可以看到enqueueMessage方法时,每次都判断是否是异步消息。这就和MessageQueue中的Next()判断联系到了一起。
c)消息的移除--都会调用消息队列中的移除方法
- public final void removeCallbacks(Runnable r){
- mQueue.removeMessages(this, r, null);
- }
- public final void removeCallbacks(Runnable r, Object token){
- mQueue.removeMessages(this, r, token);
- }
- public final void removeMessages(int what) {
- mQueue.removeMessages(this, what, null);
- }
- public final void removeMessages(int what, Object object) {
- mQueue.removeMessages(this, what, object);
- }
- public final void removeCallbacksAndMessages(Object token) {
- mQueue.removeCallbacksAndMessages(this, token);
- }
d)handleMessage(处理消息)和 dispatchMessage(分发消息)
- //处理消息
- public void handleMessage(Message msg) {
- }
- //分发消息
- public void dispatchMessage(Message msg) {
- if (msg.callback != null) {
- //当Message存在回调方法,回调方法msg.callback.run()
- handleCallback(msg);
- } else {
- //当Handler存在Callback成员变量时,回调方法mCallback.handleMessage();
- if (mCallback != null) {
- if (mCallback.handleMessage(msg)) {
- return;
- }
- }
- //Handler子类通过覆写该方法来完成具体的逻辑
- handleMessage(msg);
- }
- }
优先级:
Message的回调方法>Handler的回调方法>Handler的默认方法
6.总结
- Handler通过sendMessage()方法发送Message到MessageQueue队列
- 当前Thread中Looper通过调用loop(),不断取出达到触发条件的Message,通过对应target(Handler)的dispatchMessage()方法,将Message交给Handler的handleMessage()方法来处理。
- 一个线程对应一个Looper,一个Looper对应一个MessageQueue,一个MessageQueue可以对用多个Message。但是一个Message只能让一个handler来处理(就是Message中target所指定的handler)。
参考:
handler发送异步消息:https://blog.csdn.net/cdecde111/article/details/54670136
https://blog.csdn.net/woshiluoye9/article/details/72544764
http:///2015/12/26/handler-message-framework/
https://blog.csdn.net/iispring/article/details/47180325