Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2020-03-04:试从源码角度分析Handler的post和sendMessage方法的区别和应用场景? #239

Open
Moosphan opened this issue Mar 4, 2020 · 6 comments

Comments

@Moosphan
Copy link
Owner

Moosphan commented Mar 4, 2020

No description provided.

@SanYueSI
Copy link

SanYueSI commented Mar 4, 2020

最简单的区别就是post 是无参回调直接new Runnable就可以实现 sendMessage有参数 post一般用于单个场景 比如单一的倒计时弹框功能 sendMessage的回调需要去实现handleMessage Message则做为参数 用于多判断条件的场景 比如3个按钮 实现不同的效果

@luotuoxiangzi02
Copy link

handler.post和handler.sendMessage方法最后都会调用sendMessageAtTime方法进行消息的发送,但是在post方法中message是通过getPostMessage(Runnable r)这个方法获取的message,在这个方法中有这样一句代码m.callback = r ,给message的callback赋值为runnable对象,而在dispatchMessage这个方法中对消息进行分发的时候,先进行了msg.callback != null的判断,如果不为null,消息是通过handleCallback(msg);这个方法处理的,在这个方法中message.callback.run();调用的是post方法传递过来的runnable内的run方法处理消息,如果为空,再进行handler内部的callback判断mCallback != null,如果handler内的callback不为空,执行mCallback.handleMessage(msg)这个处理消息并判断返回是否为true,如果返回true,消息处理结束,如果返回false,消息交给handler的handleMessage(msg)处理。
所以区别就是调用post方法的消息是在post传递的Runnable对象的run方法中处理,而调用sendMessage方法需要重写handleMessage方法或者给handler设置callback,在callback的handleMessage中处理并返回true。(文字表达能力有限,抱歉)

@LvKang-insist
Copy link

post 使用的是 Runable,而 sendMessage 需要重新方法,或者设置 Callback

//应用场景:感觉那个使用符合逻辑,并且方便就用那个了

@lov3blacksilk
Copy link

post是将一个Runnbale封装成Message, 并赋值给callback参数,从这个过程之后就和sendMessge没有任何区别,会接着执行sendMessageDelayed->sendMessageAtTime,然后进入消息队列等待执行,到达Message执行时间时调用Handler的dispatchMessage方法,
其中有逻辑判断:
如果Message的callback不为空,就会执行callback的run方法,如果Message的callback为null,就会判断Handler的callback是否为空,不为空的话会执行Handler的callback的handleMessage方法,如果Handler的callback为空,则会执行Handler的handleMessage方法。
所以:

  1. post是属于sendMessage的一种赋值callback的特例
  2. post和sendMessage本质上没有区别,两种都会涉及到内存泄露的问题
  3. post方式配合lambda表达式写法更精简

话外:

  1. 现在都是使用rxjava或者其他构建好的线程切换逻辑,以前有一段时间我是手写handle的主线程和子线程切换,如果遇到这种经常需要切换线程的逻辑时,我觉得可能sendMessage方式更合适一些,举个栗子:
    post方式: Thread1.post(() -> (Thread2.post(() -> Thread1.post(.......);,这种写法嵌套好像有点儿多,但是线程切换清晰一点儿
    sendMessage写法你懂得我就不写了,只要构建好两个Handler, 代码更简洁一点儿
    这两种哪个比较好还是看个人习惯吧。
  2. 涉及到内存泄露问题时没法直接使用lambda表达式,如果有多个不同的Message需要处理的话我觉得多数场景下sendMessage更好一点儿,毕竟写一个弱引用就行了

总的来说应用场景没啥区别...

@LillteZheng
Copy link

其实没多大区别,post 只是把runnable 给 msg.callback ,而sendMessage 只是用数据给 msg,最后都是传递这个 Message。
从源码也知道,在 dispatchMessage 中,如下:

 public void dispatchMessage(Message msg) {
       if (msg.callback != null) {
           handleCallback(msg);
       } else {
           if (mCallback != null) {
               if (mCallback.handleMessage(msg)) {
                   return;
               }
           }
           handleMessage(msg);
       }
   }

如果 callback 不为空,则执行 handleCallback(msg); 方法,就是用ActivityThread去执行这个runnable,如果未null,就执行我们熟悉的 handleMessage(msg)

@mlinqirong
Copy link

handle的post和sendMessage方法的区别在于post是发送无参和执行自己实现的runnable 而sendMessage发送是带有message并执行handleMessage
post的场景是一些单于不需要标记参数和what sendMessage的场景是需要传递message标记参数是what

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants