Android异步相关-Handler

Handler机制相关

Handler的几个关键对象

Handler:Handler类几个核心对象Lopper、MessageQueue、Callback、IMessager,很明显Hadnler机制怎么跑都在这里了,后面再详细看
Looper:几个主要的对象:static Looper存储了主线程的Looper;Thread存储当前线程;MessageQueue当前线程队列;还有一个static ThreadLocal<Looper>,这个ThreadLocal大概就是用来存储的并且每个线程都只有一个互不干扰,所以这边存储跟取出的都是当前线程的Looper,详细的自查
MessageQueue:消息队列
Message:消息体

先简单来说下流程:Handler.sendMessage将Message加入MessageQueue消息队列中,Looper.prepare会存储当前线程的Looper到ThreadLocal中,Looper.loop从消息队列MessageQueue中循环取出消息交给Handler处理,最后Handler会根据一定的规则派发这些消息

第一步:Handler.sendMessage
sendMessage->sendMessageDelayed->sendMessageAtTime->enqueueMessage

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}
 boolean enqueueMessage(Message msg, long when) {
        if (msg.target == null) {
            throw new IllegalArgumentException("Message must have a target.");
        }
        if (msg.isInUse()) {
            throw new IllegalStateException(msg + " This message is already in use.");
        }

        synchronized (this) {
            if (mQuitting) {
                IllegalStateException e = new IllegalStateException(
                        msg.target + " sending message to a Handler on a dead thread");
                Log.w(TAG, e.getMessage(), e);
                msg.recycle();
                return false;
            }

            msg.markInUse();
            msg.when = when;
            Message p = mMessages;
            boolean needWake;
            if (p == null || when == 0 || when < p.when) {
                // New head, wake up the event queue if blocked.
                msg.next = p;
                mMessages = msg;
                needWake = mBlocked;
            } else {
                // Inserted within the middle of the queue.  Usually we don't have to wake
                // up the event queue unless there is a barrier at the head of the queue
                // and the message is the earliest asynchronous message in the queue.
                needWake = mBlocked && p.target == null && msg.isAsynchronous();
                Message prev;
                for (;;) {
                    prev = p;
                    p = p.next;
                    if (p == null || when < p.when) {
                        break;
                    }
                    if (needWake && p.isAsynchronous()) {
                        needWake = false;
                    }
                }
                msg.next = p; // invariant: p == prev.next
                prev.next = msg;
            }

            // We can assume mPtr != 0 because mQuitting is false.
            if (needWake) {
                nativeWake(mPtr);
            }
        }
        return true;
    }

这边会将Message加入到消息队列中
第二步:我们在子线程中会执行Looper.loop让Handler跑起来

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
        final Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }

        final long traceTag = me.mTraceTag;
        if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {
            Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
        }
          //执行处理消息的回调
        try {
            msg.target.dispatchMessage(msg);
        } finally {
            if (traceTag != 0) {
                Trace.traceEnd(traceTag);
            }
        }

        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.recycleUnchecked();
    }
}

loop()方法中有一个无限循环,不停地读取调用MessageQueue的next()方法。当next()没有返回时就阻塞在这里。当获取到MessageQueue中的消息时,就执行了处理消息的回调函数msg.target.dispatchMessage(msg)。注意,这里的msg.target就是Handler了,每个Message都会存储发送它的Handler。
第三步:Handler的处理

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

这里很简单,就是Message.mCallback>Handler.Callback>handleMessage;如果Message有设置Callback则分发给它处理,优先级最高;如无则看Handler本身有没有设置Callback有则分发給它处理,最后都没人处理则调用handleMessage处理,也是我们最常用的处理方式

Handler与主线程

子线程默认是没有消息队列MessageQueue的,而主线程只不过是 系统为我们做了这部分工作而已,相关代码就在ActivityThread.main方法中 。ActivityThread保存一个Handler,并prepare为我们创建了消息队列MessageQueue同时将主线程的Looper以静态的方式保存在Looper类中(开文有提到)。最后很容易发现主线程的各个生命周期的调用其实也是通过主线程的Handler的

public void handleMessage(Message msg) {
    ...
    switch (msg.what) {
        case LAUNCH_ACTIVITY: {
            ...
            handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
            Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
        } break;
        ...
        case PAUSE_ACTIVITY: {
            ...
            handlePauseActivity((IBinder) args.arg1, false,
                    (args.argi1 & USER_LEAVING) != 0, args.argi2,
                    (args.argi1 & DONT_REPORT) != 0, args.argi3);
            ...
        } break;

        ...
        case SHOW_WINDOW:
            ...
            handleWindowVisibility((IBinder)msg.obj, true);
            ...
            break;
        ...
        case EXIT_APPLICATION:
            if (mInitialApplication != null) {
                mInitialApplication.onTerminate();
            }
            Looper.myLooper().quit();
            break;
        ...
    }
    ...
}

Handler杂

  • Message msg = Handler.obtainMessage(),获取一个复用的Message
  • Handler h = new Handler(){handleMessage()}这样容易出现内存泄漏,需要在onDestroy中清除handler的所有消息和回调(Activity调用onDestroy结束后,若还有消息handler将继续持有Activity的引用,此无法被回收)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值