欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Android-Handler发送消息

程序员文章站 2022-07-14 16:44:46
...

Handler 发送消息

android中使用handler发送异步消息刷新UI是最基本的知识点,但如何优雅发送一个Message消息似乎很多人都是copy一个handler.sendMessage(...)

handler消息演变

        //版本1
        Message message = new Message();
        message.what = 0;
        message.obj = "hello";
        mHandler.sendMessage(message); 
        
        ↓
        
        //版本2
        Message message = mHandler.obtainMessage();
        message.what = 0;
        message.obj = "hello";
        mHandler.sendMessage(message);
        
        ↓
        
        //版本3
        mHandler.obtainMessage(0,"hello").sendToTarget();

区别

版本1->版本2的区别就是使用消息池复用消息不会重复创建Message对象,但版本2->版本3的区别是什么?网上很多文章说了一大堆看的有点乱,我总结就一个句话更加优雅了,非要说出一个区别来就是sendToTarget()不能对new的Message(没有target的Message)使用。

口说无凭上源码

先看Message类的obtain()这个方法

    /**
     * Same as {@link #obtain()}, but sets the values of the <em>target</em>, <em>what</em>, 
     * <em>arg1</em>, and <em>arg2</em> members.
     * 
     * @param h  The <em>target</em> value to set.
     * @param what  The <em>what</em> value to set.
     * @param arg1  The <em>arg1</em> value to set.
     * @param arg2  The <em>arg2</em> value to set.
     * @return  A Message object from the global pool.
     */
    public static Message obtain(Handler h, int what, int arg1, int arg2) {
        Message m = obtain();
        m.target = h;
        m.what = what;
        m.arg1 = arg1;
        m.arg2 = arg2;

        return m;
    }

target其实就是handler对象,再看一下Handler.obtainMessage()方法

    /**
     * 
     * Same as {@link #obtainMessage()}, except that it also sets the what and obj members 
     * of the returned Message.
     * 
     * @param what Value to assign to the returned Message.what field.
     * @param obj Value to assign to the returned Message.obj field.
     * @return A Message from the global message pool.
     */
    public final Message obtainMessage(int what, Object obj)
    {
        return Message.obtain(this, what, obj);
    }

最后看一下msg.sendToTarget();的实现

    /**
     * Sends this Message to the Handler specified by {@link #getTarget}.
     * Throws a null pointer exception if this field has not been set.
     */
    public void sendToTarget() {
        target.sendMessage(this);
    }

target.sendMessage(this);就相当于mHandler.sendMessage(message);,所以版本2的mHandler.sendMessage(...);和版本3的mHandler.obtainMessage(...).sendToTarget();是等价的。但版本3一行代码就可以实现着实优雅。

总结

使用mHandler.obtainMessage(...).sendToTarget();来优雅的发送消息

测试用例

@RunWith(AndroidJUnit4.class)
@LargeTest
public class HandlerAndroidTest {

    @Test
    public void testHandler() {
        Message msg = mHandler.obtainMessage(0, "hello");
        mHandler.sendMessage(msg);
        msg.sendToTarget();


        Message message = new Message();
        message.what = 0;
        message.obj = "new hello";
        mHandler.sendMessage(message);
    }

    @Before
    public void setUp() throws Exception {
        mHandler = new Handler(Looper.getMainLooper(), new Handler.Callback() {
            @Override
            public boolean handleMessage(Message msg) {
                Log.e(TAG, "callback handle message:" + msg);
                return false;
            }
        }) {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                Log.e(TAG, "override handle message:" + msg);
            }
        };
    }

    final String TAG = "HandlerTest";
    private Handler mHandler;
}