handler总结

越来越发觉handler的重要性,索性就总结一些。说到handler 就不能不说到Looper。 

Looper:就相当于一个循环,每个thread会有一个。用ThreadLocal保存着Looper,如下所示:

     /** Initialize the current thread as a looper.
      * This gives you a chance to create handlers that then reference
      * this looper, before actually starting the loop. Be sure to call
      * {@link #loop()} after calling this method, and end it by calling
      * {@link #quit()}.
      */
    public static void prepare() {
        prepare(true);
    }

    private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

所以很多时候,你看到各种例子里面,调用Looper.prepare() 就是初始化Looper。而在ui线程中会自动初始化。

Looper中有一个消息队列---MessageQueue 。 Handler 初始化的时候从本地的线程获得Looper。获得其消息队列。


Messenger 的使用:

在使用Message的时候,你会发现有个变量是Message.replyTo 其类型是Messenger 类型。

Messenger的解释就是信使。Messenger里面包含了一个handler。可以使用它发送消息。最后就是发送给Messenger里面包含的handler(mTarget)。个人的看法是,浅略地将是将Handler给封装了一下。但是其意义是不同了的,Message.replyTo 与接收到消息的handler 相互通信。

详细的例子以及参数解释可以参照:http://xwangly.iteye.com/blog/1109424

理解Messenger(Handler ) 与 Messenger(IBinder) 两个构造函数得到的mTarget(Handler 类型) 实际上是同一个Handler。


Handler 简单点理解就是往其所有的消息队列中添加消息,并且处理消息(message)。很多时候的使用就是干这两件事。handler的消息队列一般就是创建时所在的那个线程的消息队列。


handler 发送消息就是直接利用handler.sendMessage 之类的。

handler 处理消息 有很多方式。下面是Looper 中 处理消息部分的源代码,其实就是一个循环:

    /**
     * Run the message queue in this thread. Be sure to call
     * {@link #quit()} to end the loop.
     */
    public static void loop() {
        final Looper me = myLooper();
        if (me == null) {
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        final MessageQueue queue = me.mQueue;

        // Make sure the identity of this thread is that of the local process,
        // and keep track of what that identity token actually is.
        Binder.clearCallingIdentity();
        final long ident = Binder.clearCallingIdentity();

        for (;;) {
            Message msg = queue.next(); // might block
            if (msg == null) {
                // No message indicates that the message queue is quitting.
                return;
            }

            // This must be in a local variable, in case a UI event sets the logger
            Printer logging = me.mLogging;
            if (logging != null) {
                logging.println(">>>>> Dispatching to " + msg.target + " " +
                        msg.callback + ": " + msg.what);
            }

            msg.target.dispatchMessage(msg); //消息都是交给handler处理 ,所以具体处理部分就是在handler 的dispatchMessage 了。

            if (logging != null) {
                logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
            }

            // Make sure that during the course of dispatching the
            // identity of the thread wasn't corrupted.
            final long newIdent = Binder.clearCallingIdentity();
            if (ident != newIdent) {
                Log.wtf(TAG, "Thread identity changed from 0x"
                        + Long.toHexString(ident) + " to 0x"
                        + Long.toHexString(newIdent) + " while dispatching to "
                        + msg.target.getClass().getName() + " "
                        + msg.callback + " what=" + msg.what);
            }

            msg.recycle();
        }
    }


    /**
     * Handle system messages here.
     */
    public void dispatchMessage(Message msg) {
        if (msg.callback != null) {    //消息的回调函数。   1.
            handleCallback(msg);
        } else {
            if (mCallback != null) {   //handler 的回调     2.
                if (mCallback.handleMessage(msg)) {
                    return;
                }
            }
            handleMessage(msg);      //Handler 自身的内部函数,可以重载  3.
        }
    }

从dispatchMessage就可以看到整个消息的处理过程。

1. msg.callback 消息自身的处理。如果设置了,就由消息自身去处理。 其实这个类型就是一个runnable 。只不过处理的时候 直接在ui线程运行。msg.callback.run() ; 这样就让它在ui上运行了。

所以我们在设置消息的时候,在消息发送的时候,就可以去设置消息处理的方式。Message 累本身没有函数去直接设置callback 但是 Message.obtain 有一个参数是Runnable 作为Message 的callback 的。

2.mCallback handler 设置的回调。 看一下handler 的构造函数就明白了:


   /**
     * Default constructor associates this handler with the {@link Looper} for the
     * current thread.
     *
     * If this thread does not have a looper, this handler won't be able to receive messages
     * so an exception is thrown.
     */
    public Handler() {
        this(null, false);
    }

    /**
     * Constructor associates this handler with the {@link Looper} for the
     * current thread and takes a callback interface in which you can handle
     * messages.
     *
     * If this thread does not have a looper, this handler won't be able to receive messages
     * so an exception is thrown.
     *
     * @param callback The callback interface in which to handle messages, or null.
     */
    public Handler(Callback callback) {
        this(callback, false);
    }

    /**
     * Use the provided {@link Looper} instead of the default one.
     *
     * @param looper The looper, must not be null.
     */
    public Handler(Looper looper) {
        this(looper, null, false);
    }

    /**
     * Use the provided {@link Looper} instead of the default one and take a callback
     * interface in which to handle messages.
     *
     * @param looper The looper, must not be null.
     * @param callback The callback interface in which to handle messages, or null.
     */
    public Handler(Looper looper, Callback callback) {
        this(looper, callback, false);
    }

自行设置就ok了(上面的构造函数只是handler中的一部分)。CallBack接口如下:

    /**
     * Callback interface you can use when instantiating a Handler to avoid
     * having to implement your own subclass of Handler.
     */
    public interface Callback {
        public boolean handleMessage(Message msg);
    }

这是第二种处理方式。


3 第三种就是handleMessage 重载该函数即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值