Android之Handler

Android之Handler,第1张

概述Handler的整体流程Handler发送消息消息是通过MessageQueue中的enqueueMessage()方法加入消息队列中的,并且它在放入中就进行好排序,链表头的延迟时间小,尾部延迟时间最大Looper.loop()通过MessageQueue中的next()去取消息。MessageQueue中的next()如果当前链表头部消息 Handler的整体流程Handler发送消息消息是通过 MessageQueue 中的 enqueueMessage()方法加入消息队列中的,并 且它在放入中就进行好排序,链表头的延迟时间小,尾部延迟时间最大Looper.loop()通过 MessageQueue 中的 next()去取消息。MessageQueue 中的 next()如果当前链表头部消息是延迟消息,则根据延迟时间进行消息队列会 阻塞,不返回给 Looper message,直到时间到了,返回给 message如果在阻塞中有新的消息插入到链表头部则唤醒线程,MessageQueue 的nativeWake()唤醒将新消息交给回调给 handler 中的 handleMessage 后,继续调用 MessageQueue 的 next()方法,如果刚刚的延迟消息还是时间未到,则计算时间 继续阻塞。1 Handler发送消息1.1 Handler在主线程发送消息

不论是sendMessagesendEmptyMessage还是sendMessageDelayed最终都会调用enqueueMessage方法

  private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,            long uptimeMillis) {        //消息绑定Handler对象        msg.target = this;        msg.workSourceUID = ThreadLocalWorkSource.getUID();        //消息是否异步,true标识异步        if (mAsynchronous) {            msg.setAsynchronous(true);        }        //执行消息队列的入队方法,uptimeMillis表示消息的发送时间        return queue.enqueueMessage(msg, uptimeMillis);    }
1.2 Handler在子线程发送消息

在子线程创建Handler时,需在调用Looper.prepare()Looper.loop()

Looper.java  准备异步消息发送  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 是JDK中为解决多线程程序的并发问题提供了一种新的思路。使用这个工具类可以很简洁地编写出优美的多线程程序。这里存放的是Looper对象        sThreadLocal.set(new Looper(quitAllowed));    }  //创建looper的时候,也会创建当前线程的消息队列和标记当前线程线程  private Looper(boolean quitAllowed) {        mQueue = new MessageQueue(quitAllowed);        mThread = Thread.currentThread();    }
2 Looper取消息
    public static voID loop() {       //拿当前线程的looper对象        final Looper me = myLooper();        if (me == null) {            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");        }        //确保Looper.loop()调用时,保证消息队列中的消息需要执行完成        if (me.mInLoop) {            Slog.w(TAG, "Loop again would have the queued messages be executed"                    + " before this one completed.");        }        me.mInLoop = true;        final MessageQueue queue = me.mQueue;        // 核实当前线程的身份        Binder.clearCallingIDentity();        final long IDent = Binder.clearCallingIDentity();        ...        for (;;) {            //开始取消息            Message msg = queue.next(); // might block            if (msg == null) {                //无消息的时候会退出                return;            }            final Observer observer = sObserver;            ...//省略部分            //消息发送的开始时间            final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0;            final long dispatchEnd;            Object token = null;            if (observer != null) {                token = observer.messagedispatchStarting();            }            long origWorkSource = ThreadLocalWorkSource.setUID(msg.workSourceUID);            try {                //分发给Handler去处理该消息                msg.target.dispatchMessage(msg);                if (observer != null) {                    observer.messagedispatched(token, msg);                }                dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;            } catch (Exception exception) {                if (observer != null) {                    observer.dispatchingThrewException(token, msg, exception);                }                throw exception;            } finally {                //线程工作的恢复                ThreadLocalWorkSource.restore(origWorkSource);            }            ...            final long newIDent = Binder.clearCallingIDentity();            if (IDent != newIDent) {            //再次校验当前线程的身份            }            //释放消息            msg.recycleUnchecked();        }    }
3 MessageQueue的next取消息
      //取消息      for (;;) {            if (nextPollTimeoutMillis != 0) {                Binder.flushPendingCommands();            }            //仅唤醒一次            nativePollOnce(ptr, nextPollTimeoutMillis);            synchronized (this) {                // 当前时间                final long Now = SystemClock.uptimeMillis();                Message prevMsg = null;                //mMessages 表示当前等待处理的消息                Message msg = mMessages;                if (msg != null && msg.target == null) {                    // 寻找下一条异步消息                    do {                        prevMsg = msg;                        msg = msg.next;                    } while (msg != null && !msg.isAsynchronous());                }                if (msg != null) {                    if (Now < msg.when) {                        // 下一条消息未准备好,这等待,此时会进入到 Binder.flushPendingCommands()这里                        nextPollTimeoutMillis = (int) Math.min(msg.when - Now, Integer.MAX_VALUE);                    } else {                        //当前不是阻塞状态                        mBlocked = false;                        if (prevMsg != null) {                            prevMsg.next = msg.next;                        } else {                            mMessages = msg.next;                        }                        msg.next = null;                        msg.markInUse();                        return msg;                    }                } else {                    //没有更多消息 不需要循环                    nextPollTimeoutMillis = -1;                }                // 空闲的IDleHandler数量                if (pendingIDleHandlerCount < 0                        && (mMessages == null || Now < mMessages.when)) {                    pendingIDleHandlerCount = mIDleHandlers.size();                }                if (pendingIDleHandlerCount <= 0) {                    // 没有空闲的处理程序,循环等待更多                    mBlocked = true;                    continue;                }                if (mPendingIDleHandlers == null) {                    mPendingIDleHandlers = new IDleHandler[Math.max(pendingIDleHandlerCount, 4)];                }                mPendingIDleHandlers = mIDleHandlers.toArray(mPendingIDleHandlers);            }            // 运行空闲的处理程序,仅限在第一次迭代时会到达这里.            for (int i = 0; i < pendingIDleHandlerCount; i++) {                final IDleHandler IDler = mPendingIDleHandlers[i];                mPendingIDleHandlers[i] = null; // release the reference to the handler                boolean keep = false;                try {                    keep = IDler.queueIDle();                } catch (Throwable t) {                    Log.wtf(TAG, "IDleHandler threw exception", t);                }                if (!keep) {                    synchronized (this) {                        mIDleHandlers.remove(IDler);                    }                }            }            pendingIDleHandlerCount = 0;            //不影响下次下次消息的获取,保持的调用Binder.flushPendingCommands()一致。            nextPollTimeoutMillis = 0;        }
HandlerThread的使用
        HandlerThread handlerThread = new HandlerThread("xxx");        handlerThread.start();//Looper.prepare();不用我们再次调用        //拿到新创建的线程的looper来创建Handler        Looper looper = handlerThread.getLooper();        Handler handler2 = new Handler(looper);        handler2.sendMessage(Message);
小纸片记住ThreadLocal是用来区分Handler主线程MessageQueue的next()不仅你会使用,系统的异步刷新UI也会使用 总结

以上是内存溢出为你收集整理的Android之Handler全部内容,希望文章能够帮你解决Android之Handler所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1003183.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-22
下一篇 2022-05-22

发表评论

登录后才能评论

评论列表(0条)

保存