资讯专栏INFORMATION COLUMN

『 面试题 』之 Android中的消息机制?

A Loity / 2899人阅读

摘要:然后被主线程或者是实例化化的线程的循环到,然后执行。最终走向最终把我们的,放进了主线程的里面进行循环

其实问这种问题,无非就是想知道你对handler了解怎么样。虽然handler这种问题已经被问烂了,但是很多公司,尤其是中小型企业,

被问的几率还是很高,所以,再次记录一下,也很简单,没事儿的时候点进源码看看就明白。

Android 的 多线程通讯核心类是Handler!

通常我们在使用多线程通讯的方式,是在 线程A(或UI线程) 中创建 handler,在线程B中 使用 handler的实例,调用其方法 例如:sendMessage(Message msg)sendEmptyMessage(int what),发送我们需要传送的数据放进了Messagequeue里面。然后被主线程或者是实例化化handler的线程 的Looper循环到,然后执行。

通过源码我们大致可以理出一条线路来:

需要注意的是,ThreadLocal 该类是用于创建线程局部变量的类,我们知道,通常情况下一个变量是在多个线程中都能访问的,但是ThreadLocal,可创建一个只在当前线程访问的变量。他支持泛型,回到我们的面试题上

这里 我们可以逐步分析:

public Handler(Callback callback, boolean async) {
        
       //得到主线程(已经被ActivityThread初始化好)的looper
       mLooper = Looper.myLooper();
       if (mLooper == null) {
           throw new RuntimeException(
               "Can"t create handler inside thread that has not called Looper.prepare()");
       }
       
       //得到主线程(已经被ActivityThread初始化好)的looper的MessageQueue,注释:①
       mQueue = mLooper.mQueue;
       mCallback = callback;
       mAsynchronous = async;
}

注意,看到了吗? 这里是核心:mLooper = Looper.myLooper();

public static Looper myLooper() {
     return sThreadLocal.get();
}
    

而这个Looper对象,是在我们启动程序的时候,也就是ActivityThread 中的main方法帮我们初始化的,也就是我们主线程的Looper。

public static void prepareMainLooper() {
     ···
     prepare(false);
     ···
}

--------------------------------------------------

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));
}

我们在子线程 使用 handler的实例进行 sendMessage(Message msg) 的时候:

    public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
        //这里的代码和上面的注释①对应。
        MessageQueue queue = mQueue;
        if (queue == null) {
            RuntimeException e = new RuntimeException(
                    this + " sendMessageAtTime() called with no mQueue");
            Log.w("Looper", e.getMessage(), e);
            return false;
        }
        return enqueueMessage(queue, msg, uptimeMillis);
    }

最终走向enqueueMessage:

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
    msg.target = this;
    if (mAsynchronous) {
        msg.setAsynchronous(true);
    }
    return queue.enqueueMessage(msg, uptimeMillis);
}

最终把我们的Message,放进了主线程的MessageQueue里面进行循环!

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/14041.html

相关文章

  • 金九银十中,看看这31道Android面试

    摘要:静态集合类引起内存泄露主要是,等,如果是静态集合这些集合没有及时的话,就会一直持有这些对象。关于合理使用内存,其实就是避免内存泄露中已经说明。参数原生参数元素需要支持机制参考进程线程管理一消息机制的框架这个系类。 阅读目录 1.如何对 Android 应用进行性能分析 2.什么情况下会导致内存泄露 3.如何避免 OOM 异常 4.Android 中如何捕获未捕获的异常 5.ANR 是...

    call_me_R 评论0 收藏0
  • 安卓控件 - 收藏集 - 掘金

    摘要:掘金效果图使用方法依赖注意使用时需要在父布局中加入中的消息传递机制掘金引言在日常开发工作中,想必大家或多或少都会遇到数据传输的需要。 杭州找 Android 工作的点点滴滴 - 掘金写在前面的话 我从14年毕业到现在一直待一个三线城市,就用 C 市 代替吧。地方很小,适合居住,但不适合 it 开发,城市很小、圈子很小,it 不发达,想要在 it 上面有出路的还是得去北上广深大城市。我在...

    yintaolaowanzi 评论0 收藏0
  • Android Studio

    摘要:应用程序响应速度最糟糕的是应用程序无响应对话框。然而,不幸的是,并不能获取所要的结果,宽高值均为。提供侧滑操作的控件这是一款提供侧滑功能的,可以设置它的滑动方向左右上下。 写给 Android 开发者的混淆使用手册 点击打开链接 毫无疑问,混淆是打包过程中最重要的流程之一,在没有特殊原因的情况下,所有 app 都应该开启混淆。 首先,这里说的的混淆其实是包括了代码压缩、代码混淆以及资源...

    dunizb 评论0 收藏0
  • Android&Java面试大全—金九银十面试必备

    摘要:需要校验字节信息是否符合规范,避免恶意信息和不规范数据危害运行安全。具有相同哈希值的键值对会组成链表。通过在协议下添加了一层协议对数据进行加密从而保证了安全。常见的非对称加密包括等。 类加载过程 Java 中类加载分为 3 个步骤:加载、链接、初始化。 加载。 加载是将字节码数据从不同的数据源读取到JVM内存,并映射为 JVM 认可的数据结构,也就是 Class 对象的过程。数据源可...

    Labradors 评论0 收藏0
  • Android&Java面试大全—金九银十面试必备

    摘要:需要校验字节信息是否符合规范,避免恶意信息和不规范数据危害运行安全。具有相同哈希值的键值对会组成链表。通过在协议下添加了一层协议对数据进行加密从而保证了安全。常见的非对称加密包括等。 类加载过程 Java 中类加载分为 3 个步骤:加载、链接、初始化。 加载。 加载是将字节码数据从不同的数据源读取到JVM内存,并映射为 JVM 认可的数据结构,也就是 Class 对象的过程。数据源可...

    renweihub 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<