android handler机制

Handlerandroid提供的一种异步回调机制,android UI界面运行于ActivityThread主线程中,UI的刷新只能在主线程进行,主线程不能阻塞,也就是不能做一些超时的操作,例如网络请求。所以一般我们都会开启新的线程来进行网络数据的获取,在获取完成后需要通知UI进行界面的刷新。而UI运行于主线程,需要有个消息机制来通知它进行刷新。而handler就可以用于线程发送的数据并用此数据配合主线程更新UI

UI主线程中只要定义一个Handler并实现handleMessage方法,该方法能够获取子线程传来的消息,然后在UI主线程进行处理。那么handler是怎么发送消息的呢,主界面又是怎么收到消息的呢。

Android的这种线程间通信机制主要通过下面四个类实现:HanlderLooperMessageQueueMessage,其中Handler是消息的收发器,MessageQueue是一个消息队列,每个线程都有其对应的消息队列,Message是消息类,Looper可以理解为一个循环取消息的线程,它与一个消息队列进行绑定,并设置到当前线程的ThreadLocal中。


我们在主线程中首先会Handler mHandler = new Handler();并实现handleMessage方法。然后当异步线程处理结束后通过调用mHandler.sendMessage(msg)发送一个消息到主线程,该消息会插入到MessageQueue中(queue.enqueueMessage(msg, uptimeMillis)),handler在初始化时,会获取当前线程的Looper对象和MessageQueue队列,代码如下:

 public Handler(Callback callback, boolean async) {

        ..........

        mLooper = Looper.myLooper();

        if (mLooper == null) {

            throw new RuntimeException(

                "Can't create handler inside thread that has not called Looper.prepare()");

        }

        mQueue = mLooper.mQueue; 

    }

 

 其中Looper.myLooper,用于获取当前线程对应的Looper对象,如下所示:

 public static Looper myLooper() {

        return sThreadLocal.get();

}

Looper为空时就会报异常,也就是说我们在子线程中如果不创建Looper对象就会报异常。但我们并没有在UI主线程中使用sThreadLocal.set()方法啊,那么ThreadLocalLooper对象时什么时候设置进去的呢?原来在ActivityThread,也就是UI主线程中,android给我们进行了默认的设置:

 public static void main(String[] args) {

          ................

      Looper.prepareMainLooper();

      Looper.loop()

 }

    在prepareMainLooper方法中就会位当前UI线程设置一个Looper对象,loop用于进入循环的消息处理中。在我们自己定义的子线程中如果想使用Handler,需要采用如下的方式实现:

Loper.prepare();//为当前线程创建一个Looper对象,和MessageQueue

Handler mHandler = new Handler();

Looper.loop();//进入消息循环

 

Loop方法主要代码如下,主要用于循环取出MessageQueue队列中的消息,发送到目的地进行处理。

 public static void loop() {

        final Looper me = myLooper()

        final MessageQueue queue = me.mQueue;

        for (;;) {

            Message msg = queue.next(); // might block

            msg.target.dispatchMessage(msg);

        }

    }

可以看出Loop方法首先获取当前线程的Looper对象和对应的MessageQueue,然后循环取出每个消息,通过 msg.target发送消息出去,target其实就是Handle对象,在handle发送消息的时候就已经绑定了的

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {

        msg.target = this;

        if (mAsynchronous) {

            msg.setAsynchronous(true);

        }

        return queue.enqueueMessage(msg, uptimeMillis);

    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值