zoukankan      html  css  js  c++  java
  • 消息机制——handler

    android消息机制——handler

    为啥要有消息机制?

    android有个主线程,activityThread,可以操作UI,其他线程不能更新UI。APP开发过程中经常遇到耗时操作,如文件读写,网络请求等。如果把这些耗时请求都放在主线程上面,会发生ANR(Application Not Responding)。针对这种情况,一般的解决措施都是另开个线程去执行这些耗时操作,当这些耗时操作执行完,需要更新UI,咋办?这个时候消息机制就可以大显身手,发送message,告诉主线程,去更新UI。

    ANR?

    三种类型:

    • KeyDispatchTimeout(5 seconds) ——按键或触摸事件在特定时间内无响应
    • BroadcastTimeout(10 seconds) ——BroadcastReceiver在特定时间内无法处理完成
    • ServiceTimeout(20 seconds) ——Service在特定的时间内无法处理完成

    两种原因:

    • 当前事件没有及时完成
    • 当前事件迟迟没有被处理

    Handler如何成为通讯员?

    ActivityThread被创建时会创建looper,lopper的构造方法里面创建MessageQueue。

    • Handler的send与post都会sendMessage,执行enQueueMessage方法,向MessageQueue中插入一条message。
    private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
            msg.target = this;
            if (mAsynchronous) {
                msg.setAsynchronous(true);
            }
            return queue.enqueueMessage(msg, uptimeMillis);
    }
    
    • looper会不断轮询QueueMessage的next方法。
    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.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();
            }
        }
    
    • 发现message,就会执行handler中的dispathMessage,dispathMessage被调用后,调用handlerMessage方法。
    try {
        msg.target.dispatchMessage(msg);
    } finally {
        if (traceTag != 0) {
            Trace.traceEnd(traceTag);
        }
    }
    
    public void dispatchMessage(Message msg) {
            if (msg.callback != null) {
                handleCallback(msg);
            } else {
                if (mCallback != null) {
                    if (mCallback.handleMessage(msg)) {
                        return;
                    }
                }
                handleMessage(msg);
            }
        }
    

    随便提下

    当 MessageQueue中没有message且没有空闲的handler可以处理的时候,通过nativePollOnce将循环阻塞与此。enqueueMessage后,再重新通过nativeWake唤醒。

  • 相关阅读:
    (引)spring学习笔记1.什么是控制反转
    Arduino 各种模块篇 步进电机 step motor 舵机 servo 直流电机 总复习
    Raspberry Pi Wireless Adaptor
    Pyramid 使用总结1
    Arduino 各种模块篇 人体红外感应模块 proximity sensor
    Pyramid 使用总结2
    Webcam Streaming Desktop Recording on Linux for ubuntu or its destros
    Arduino 各种模块篇 步进电机 step motor( 不用库,不用shield, 纯)
    Arduino 各种模块篇 motor shield 电机扩展板(舵机、直流电机、步进电机party)
    转载 stepper motors
  • 原文地址:https://www.cnblogs.com/qinhe/p/6370838.html
Copyright © 2011-2022 走看看