Android消息机制-Handler(二)

本文详细介绍了Android Handler的两类使用方法——send与post,包括它们各自的执行方式和区别。send方法涉及sendEmptyMessage、sendMessage等,而post方法包括post(Runnable)和postDelayed(Runnable)等。所有send方法最终都会调用dispatchMessage方法,post方法通过msg.callback执行Runnable对象。send和post的本质区别不大,最终都在dispatchMessage中执行,不同在于Message的处理方式。Handler可以通过实现Callback接口或重写handleMessage方法来处理Message。
摘要由CSDN通过智能技术生成

一.Handler的两类使用方法

Handler里面有两类方法,一类是sendxxxx(),另一类是postxxxxx()

A. sendxxxx方法

1.sendEmptyMessage(int what):只发送了一个what值,也就是handleMessage收到的msg里面what的值

2.sendEmptyMessageDelayed(int what,long delayMillis):  指定延时多少毫秒后发送what

3.sendMessage(Message msg):立即发送信息,需要传入一个Message对象作为参数

4.sendMessageDelayed(Message msg, long delayMillis):延迟一定时间发送message对象

5.sendEmptyMessageAtTime(int what, long uptimeMillis):在一具体时间发送空消息

6.sendMessageAtTime(Message msg, long uptimeMillis):不说也知道了,在一具体时间发送message对象

7.sendMessageAtFrontOfQueue(Message msg):插入消息队列的头部,然后next就是它执行了

注:以上在handler源码里除了7 sendMessageAtFrontOfQueue 最终没有调用 sendMessageAtTime 方法外,其他方法最终都指向了    sendMessageAtTime方法

B.postXXX方法

1.post(Runnable r):Runable对象作为参数,post完之后,直接可以执行,Runable对象里面的run方法

2.postDelayed(Runnable r, long delayMillis):延迟一定时间执行runable对象

3.postAtTime(Runnable r, long uptimeMillis)在一具体时间执行runable对象

4.postAtFrontOfQueue(Runnable r):在消息队列头部插入runable对象执行


post方法执行举例

package practise.heima.com.customview;

import android.app.Activity;
import android.os.Handler;
import android.os.Bundle;
import android.widget.TextView;

public class HandlerActivity extends Activity {

    private TextView tv;
    Handler handler=new Handler();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_mhandler);
        tv= (TextView) findViewById(R.id.tv);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                tv.setText("Runable 对象执行");
            }
        },2000);//利用post方法,延迟两秒执行Runbale
    }
}


二 send 和post方式有什么区别吗?

其实只是实现形式的不同,区别不大。不管是send或者post 最终的执行都是在 dispatchMessage(Message msg) 里面,源码如下:

 public void dispatchMessage(Message msg) {
        if (msg.callback != null) {  //如果message对象里面的callback不为空执行handleCallback(msg)
            handleCallback(msg);
        } else {//否则的话
		//如果handler对象里的 mCallback不为空的话,就执行mCallback的handleMessage(msg)方法
            if (mCallback != null) {
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
		//mCallback为空的话,就执行Handler的handleMessage(msg)方法
            handleMessage(msg);
        }
    }

可以发现,dispatchMessage做了两个if判断,也就是有三种执行方法。

    A.post方法的执行

post方法对应的是msg.callback != null 的判断,这个是Message对象里面定义的callback属性,是个Runable对象,

Runnable callback;
其实去看Handler类里post方法源码可以发现post方法的Runnable对象参数,通过getPostMessage(Runnable r)生成了一个有Runnable类型属性的Message对象,并调用sendMessageDelayed 把这个包含Runnable对象的Message发出去了。

 public final boolean post(Runnable r)
    {
       return  sendMessageDelayed(getPostMessage(r), 0);
    }

 private static Message getPostMessage(Runnable r) {
        Message m = Message.obtain();
        m.callback = r;
        return m;
    }
当dispatchMessage收到消息的时候判断message的callback是否为空,不为空,就用handleCallback(msg),执行了最开始传递进来的Runnable对象
 private static void handleCallback(Message message) {
        message.callback.run();
    }

B.send方法的执行

send方法对应的是最后的Handler的handleMessage(msg) 的执行,这个执行的一般都是我们在定义handler时,重写的handleMessage(msg) 方法。

Message的target属性是Handler类型,在让消息排队的时候执行enqueueMessage方法,在里面,handler对象本身让message对象给打包排队去了,并最终执行

 private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

C.mCallback  的执行

Handler定义了一个 Callback接口。通过看源码发现,dispatchMessage 里面的 mCallback 属性,都是通过构造函数赋值的,也就是说,在new handler对象的时候,就可以传递一个实现了Callback接口的对象进来,最终可以在dispatchMessage 里面执行这个实现Callback接口的对象的参数的handleMessage(msg)方法。

所以,使得Handler能够处理Message,我们有两种办法: 
1. 向Hanlder的构造函数传入一个Handler.Callback对象,并实现Handler.Callback的handleMessage方法 
2. 无需向Hanlder的构造函数传入Handler.Callback对象,但是需要重写Handler本身的handleMessage方法 

也就是说无论哪种方式,我们都得通过某种方式实现handleMessage方法

还有一点,这种方法是可以带有返回值的,如果返回false,可以既执行mCallback的handleMessage(msg)方法,又可以执行重写的handler的handleMessage(msg)方法

使用Callback形式的handler

Handler handler=new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            return false;
        }
    }){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };

 Handler handler=new Handler(new Handler.Callback() {
        @Override
        public boolean handleMessage(Message msg) {
            Log.e("HandlerActivity","handler执行Callback()");
            return false;//false 则handler本身重写的handleMessage会执行,true不会
        }
    }){
        @Override
        public void handleMessage(Message msg) {
            Log.e("HandlerActivity","handler执行handleMessage()");
        }
    };




源码里有关mCallback的地方。
final Callback mCallback;

    public interface Callback {
        public boolean handleMessage(Message msg);
    }

    public Handler(Looper looper, Callback callback, boolean async) {
        mLooper = looper;
        mQueue = looper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }

   public Handler(Callback callback, boolean async) {
        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());
            }
        }

        mLooper = Looper.myLooper();
        if (mLooper == null) {
            throw new RuntimeException(
                "Can't create handler inside thread that has not called Looper.prepare()");
        }
        mQueue = mLooper.mQueue;
        mCallback = callback;
        mAsynchronous = async;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值