Android消息机制原理解析

【Android】Handler、Looper、消息队列运行机制原理解析及相关面试题 简历首选内推方式,速度快,效率高啊!然后可以在拉钩,boss,脉脉,大街上看看。简历上写道熟悉什么技术就一定要去熟悉它,不然被问到不会很尴尬!做过什么项目,即使项目体量不大,但也一定要熟悉实现原理!不是你负责的部分,也可以看看同事是怎么实现的,换你来做你会怎么做?做过什么,会什么是广度问题,取决于项目内容。但做过什么,达到怎样一个境界,这是深度问题,和个人学习能力和解决问题的态度有关了。大公司看深度,小公司看广度。大公司面试你会的,小公司面试他们用到的你会不会,也就是岗位匹配度。面试过程一定要有礼貌! 阅读详情

消息机制流程简介

在应用启动的时候,会执行程序的入口函数main(),main()里面会创建一个Looper对象,然后通过这个Looper对象开启一个死循环,这个循环的工作是,不断的从消息队列MessageQueue里面取出消息即Message对象,并处理。然后看下面两个问题:

  • 循环拿到一个消息之后,如何处理?

是通过在Looper的循环里调用Handler的dispatchMessage()方法去处理的,而dispatchMessage()方法里面会调用handleMessage()方法,handleMessage()就是平时使用Handler时重写的方法,所以最终如何处理消息由使用Handler的开发者决定。

  • MessageQueue里的消息从哪来?

使用Handler的开发者通过调用sendMessage()方法将消息加入到MessageQueue里面。

上面就是Android中消息机制的一个整体流程,也是 “Android中Handler,Looper,MessageQueue,Message有什么关系?” 的答案。通过上面的流程可以发现Handler在消息机制中的地位,是作为辅助类或者工具类存在的,用来供开发者使用。

对于这个流程有两个疑问:

  • Looper中是如何能调用到Handler的方法的?

  • Handler是如何能往MessageQueue中插入消息的?

这两个问题会在后面给出答案,下面先来通过源码,分析一下这个过程的具体细节:

消息机制的源码分析

首先main()方法位于ActivityThread.java类里面,这是一个隐藏类,源码位置:frameworks/base/core/java/android/app/ActivityThread.java

public static void main(String[] args) { 
    ...... 
    Looper.prepareMainLooper(); 

    ActivityThread thread = new ActivityThread(); 
    thread.attach(false); 

    if (sMainThreadHandler == null) { 
        sMainThreadHandler = thread.getHandler(); 
    } 

    Looper.loop(); 

    throw new RuntimeException("Main thread loop unexpectedly exited"); 
}

Looper的创建可以通过Looper.prepare()来完成,上面的代码中prepareMainLooper()是给主线程创建Looper使用的,本质也是调用的prepare()方法。创建Looper以后就可以调用Looper.loop()开启循环了。main方法很简单,不多说了,下面看看Looper被创建的时候做了什么,下面是Looper的prepare()方法和变量sThreadLocal:

static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>(); 

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

很简单,new了一个Looper,并把new出来的Looper保存到ThreadLocal里面。ThreadLocal是什么?它是一个用来存储数据的类,类似HashMap、ArrayList等集合类。它的特点是可以在指定的线程中存储数据,然后取数据只能取到当前线程的数据,比如下面的代码:

ThreadLocal<Integer> mThreadLocal = new ThreadLocal<>(); 
private void testMethod() { 

    mThreadLocal.set(0); 
    Log.d(TAG, "main  mThreadLocal=" + mThreadLocal.get()); 

    new Thread("Thread1") { 
        @Override 
        public void run() { 
            mThreadLocal.set(1); 
            Log.d(TAG, "Thread1  mThreadLocal=" + mThreadLocal.get()); 
        } 
    }.start(); 

    new Thread("Thread2") { 
        @Override 
        public void run() { 
            mThreadLocal.set(2); 
            Log.d(TAG, "Thread1  mThreadLocal=" + mThreadLocal.get()); 
        } 
    }.start(); 

    Log.d(TAG, "main  mThreadLocal=" + mThreadLocal.get()); 
}

输出的log是

main  mThreadLocal=0 
Thread1  mThreadLocal=1
Thread2  mThreadLocal=2
main  mThreadLocal=0

通过上面的例子可以清晰的看到ThreadLocal存取数据的特点,只能取到当前所在线程存的数据,如果所在线程没存数据,取出来的就是null。其实这个效果可以通过HashMap<Thread, Object>来实现,考虑线程安全的话使用ConcurrentMap<Thread, Object>,不过使用Map会有一些麻烦的事要处理,比如当一个线程结束的时候我们如何删除这个线程的对象副本呢?如果使用ThreadLocal就不用有这个担心了,ThreadLocal保证每个线程都保持对其线程局部变量副本的隐式引用,只要线程是活动的并且 ThreadLocal 实例是可访问的;在线程消失之后,其线程局部实例的所有副本都会被垃圾回收(除非存在对这些副本的其他引用)。更多ThreadLocal的讲解参考:Android线程管理之ThreadLocal理解及应用场景,地址如下:

https://www.cnblogs.com/whoislcj/p/5811989.html

好了回到正题,prepare()创建Looper的时候同时把创建的Looper存储到了ThreadLocal中,通过对ThreadLocal的介绍,获取Looper对象就很简单了,sThreadLocal.get()即可,源码提供了一个public的静态方法可以在主线程的任何地方获取这个主线程的Looper(注意一下方法名myLooper(),多个地方会用到):

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

Looper创建完了,接下来开启循环,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; 

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

        try { 
            msg.target.dispatchMessage(msg); 
        } finally { 
            if (traceTag != 0) { 
                Trace.traceEnd(traceTag); 
            } 
        } 

        msg.recycleUnchecked(); 
    } 
}

上面的代码,首先获取主线程的Looper对象,然后取得Looper中的消息队列final MessageQueue queue = me.mQueue;,然后下面是一个死循环,不断的从消息队列里取消息Message msg = queue.next();,可以看到取出的消息是一个Message对象,如果消息队列里没有消息,就会阻塞在这行代码,等到有消息来的时候会被唤醒。取到消息以后,通过msg.target.dispatchMessage(msg);来处理消息,msg.target 是一个Handler对象,所以这个时候就调用到我们重写的Hander的handleMessage()方法了。

msg.target 是在什么时候被赋值的呢?要找到这个答案很容易,msg.target是被封装在消息里面的,肯定要从发送消息那里开始找,看看Message是如何封装的。那么就从Handler的sendMessage(msg)方法开始,过程如下:

public final boolean sendMessage(Message msg) { 
    return sendMessageDelayed(msg, 0); 
} 

public final boolean sendMessageDelayed(Message msg, long delayMillis) { 
    if (delayMillis < 0) { 
        delayMillis = 0; 
    } 
    return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis); 
} 

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

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

可以看到最后的enqueueMessage()方法中msg.target = this;,这里就把发送消息的handler封装到了消息中。同时可以看到,发送消息其实就是往MessageQueue里面插入了一条消息,然后Looper里面的循环就可以处理消息了。Handler里面的消息队列是怎么来的呢?从上面的代码可以看到enqueueMessage()里面的queue是从sendMessageAtTime传来的,也就是mQueue。然后看mQueue是在哪初始化的,看Handler的构造方法如下:

public Handler(Callback callback, boolean async) { 
    if (FIND_POTENTIAL_LEAKS) { 
        final Class<? extends Handler> klass = getClass(); 
        if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && 
                (klass.getModifiers() & Modifier.STATIC) == 0) { 
            Log.w(TAG, "The following Handler class should be static or leaks might occur: " + 
                klass.getCanonicalName()); 
        } 
    } 

    mLooper = Looper.myLooper(); 
    if (mLooper == null) { 
        throw new RuntimeException( 
            "Can't create handler inside thread that has not called Looper.prepare()"); 
    } 
    mQueue = mLooper.mQueue; 
    mCallback = callback; 
    mAsynchronous = async; 
}

mQueue的初始化很简单,首先取得Handler所在线程的Looper,然后取出Looper中的mQueue。这也是Handler为什么必须在有Looper的线程中才能使用的原因,拿到mQueue就可以很容易的往Looper的消息队列里插入消息了(配合Looper的循环+阻塞就实现了发送接收消息的效果)。

以上就是主线程中消息机制的原理。

那么,在任何线程下使用handler的如下做法的原因、原理、内部流程等就非常清晰了:

new Thread() { 
    @Override 
    public void run() { 
        Looper.prepare(); 
        Looper.loop(); 
        Handler handler = new Handler(); 
    } 
}.start();
  1. 首先Looper.prepare()创建Looper并初始化Looper持有的消息队列MessageQueue,创建好后将Looper保存到ThreadLocal中方便Handler直接获取。

  2. 然后Looper.loop()开启循环,从MessageQueue里面取消息并调用handler的 dispatchMessage(msg) 方法处理消息。如果MessageQueue里没有消息,循环就会阻塞进入休眠状态,等有消息的时候被唤醒处理消息。

  3. 再然后我们new Handler()的时候,Handler构造方法中获取Looper并且拿到Looper的MessageQueue对象。然后Handler内部就可以直接往MessageQueue里面插入消息了,插入消息即发送消息,这时候有消息了就会唤醒Looper循环去处理消息。处理消息就是调用dispatchMessage(msg) 方法,最终调用到我们重写的Handler的handleMessage()方法。

通过一些问题的研究加强对消息机制的理解

源码分析完了,下面看一下文章开头的两个问题:

  • Looper中是如何能调用到Handler的方法的?

  • Handler是如何能往MessageQueue中插入消息的?

这两个问题源码分析中已经给出答案,这里做一下总结,首先搞清楚以下对象在消息机制中的关系:

  • Looper,MessageQueue,Message,ThreadLocal,Handler

  • Looper对象有一个成员MessageQueue,MessageQueue是一个消息队列,用来存储消息Message

  • Message消息中带有一个handler对象,所以Looper取出消息后,可以很方便的调用到Handler的方法(问题1解决)

  • Message是如何带有handler对象的?是handler在发送消息的时候把自己封装到消息里的。

  • Handler是如何发送消息的?是通过获取Looper对象从而取得Looper里面的MessageQueue,然后Handler就可以直接往MessageQueue里面插入消息了。(问题2解决)

  • Handler是如何获取Looper对象的?Looper在创建的时候同时把自己保存到ThreadLocal中,并提供一个public的静态方法可以从ThreadLocal中取出Looper,所以Handler的构造方法里可以直接调用静态方法取得Looper对象。

带着上面的一系列问题看源码就很清晰了,下面是知乎上的一个问答

  • Android中为什么主线程不会因为Looper.loop()里的死循环卡死?

原因很简单,循环里有阻塞,所以死循环并不会一直执行,相反的,大部分时间是没有消息的,所以主线程大多数时候都是处于休眠状态,也就不会消耗太多的CPU资源导致卡死。

  1. 阻塞的原理是使用Linux的管道机制实现的

  2. 主线程没有消息处理时阻塞在管道的读端

  3. binder线程会往主线程消息队列里添加消息,然后往管道写端写一个字节,这样就能唤醒主线程从管道读端返回,也就是说looper循环里queue.next()会调用返回...

这里说到binder线程,具体的实现细节不必深究,考虑下面的问题:

  • 主线程的死循环如何处理其它事务?

首先需要看懂这个问题,主线程进入Looper死循环后,如何处理其他事务,比如activity的各个生命周期的回调函数是如何被执行到的(注意这里是在同一个线程下,代码是按顺序执行的,如果在死循环这阻塞了,那么进入死循环后循环以外的代码是如何执行的)。

首先再看main函数的源码

Looper.prepareMainLooper(); 

ActivityThread thread = new ActivityThread(); 
thread.attach(false); 

if (sMainThreadHandler == null) { 
    sMainThreadHandler = thread.getHandler(); 
} 

Looper.loop();

在Looper.prepare和Looper.loop之间new了一个ActivityThread并调用了它的attach方法,这个方法就是开启binder线程的,另外new ActivityThread()的时候同时会初始化它的一个H类型的成员,H是一个继承了Handler的类。此时的结果就是:在主线程开启loop死循环之前,已经启动binder线程,并且准备好了一个名为H的Handler,那么接下来在主线程死循环之外做一些事务处理就很简单了,只需要通过binder线程向H发送消息即可,比如发送 H.LAUNCH_ACTIVITY 消息就是通知主线程调用Activity.onCreate() ,当然不是直接调用,H收到消息后会进行一系列复杂的函数调用最终调用到Activity.onCreate()。

至于谁来控制binder线程来向H发消息就不深入研究了,下面是《Android开发艺术探索》里面的一段话:

ActivityThread 通过 ApplicationThread 和 AMS 进行进程间通讯,AMS 以进程间通信的方式完成 ActivityThread 的请求后会回调 ApplicationThread 中的 Binder 方法,然后 ApplicationThread 会向 H 发送消息,H 收到消息后会将 ApplicationThread 中的逻辑切换到 ActivityThread 中去执行,即切换到主线程中去执行,这个过程就是主线程的消息循环模型。

这个问题就到这里,更多内容看知乎原文

https://www.zhihu.com/question/34652589


结语


和其他系统相同,Android应用程序也是依靠消息驱动来工作的。网上的这句话还是很有道理的。

项目地址:

https://www.jianshu.com/p/6cc4d4b4676b

如果有什么问题欢迎留言哈,谢谢!

android消息处理机制原理解析 android Handler Looper MessageQueue 阅读详情

相关推荐

VS2019 +osg3.6.5+ earth3.2+qt5.14.2+osgQt 编译教程

用vs新建工程,稍后会在写一篇博客上分享四、结语至此,所有的编译就均已完成。

king_ink的博客 1134

Android 消息机制

Android 消息机制

EnHengNa的博客 1004

【医学图像分割网络】之Res U-Net网络PyTorch复现

【医学图像分割网络】之Res U-Net网络PyTorch复现 1.内容 U-Net网络算是医学图像分割领域的开山之作,我接触深度学习到现在大概将近大半年时间,看到了很多基于U-Net网络的变体,后续也会继续和大家一起分享学习。这次分享ResNet+U-Net的一个改进版,ResNet本身就是一个十分优秀的backbone,目前应用仍然十分广泛,我们融合进ResNet后,我们就可以使得U-Net进行迁移学习了。 1.将Resnet作为encoder替换U-Net原始结构 2.U-Net提出时间较早,当时还没

qq_39071739的博客 1万+

Android 知识总结:消息机制

Android 的消息机制主要是指 Handler 的运行机制以及 Handler 所附带的 MessageQueue 和 Looper 的工作过程,这三者实际上是一个整体,只不过我们在开发过程中比较多地接触到 Handler 而已。

耐心的L的博客 1116

从临床试验到互联网AB测试:边缘结构模型(MSM)如何解决‘时依性混杂’这个老大难问题

本文探讨边缘结构模型(MSM)如何解决时依性混杂问题,适用于临床试验和互联网AB测试。通过逆概率加权(IPTW)等方法,MSM能有效剥离混杂效应,准确评估长期干预效果。文章结合跨领域案例,详细解析MSM的核心原理、实施步骤及在推荐算法效果评估中的实战应用,帮助读者掌握这一先进因果推断工具。

weixin_28725949的博客 207

CESM笔记——CESM1.0-CESM1.2.2-CESM2.1.3三个版本模式工作流对比

最近测试了CESM1.0,CESM1.2.2和CESM2.1.3三个版本,不同版本在workflow上有一些区别,来做点笔记。 CESM1.0 测试compset:B_2000,F_2000 workflow: 1. create_newcase -case ~/CESM/cesm1_0/script/B_2000 -compset B_2000 -res f19_g16 -mach tianhe 2. cd B_2000 (optional) env_mach_pes.xml ##修改核数,

砍柴姑娘Jourosy的博客 4944

Android消息机制原理全面讲解

一、简介 消息机制这个知识点,从我们第一天写android应用时就接触到了,可能大部分时间我们都用它来更新主线程的UI界面,使用上应该没事问题,但是知其然还要知其所以然,今天就让我们通过一篇文章彻底的,透彻的,永久的理解并记住Android消息机制的原理。整篇文章会围绕下面几个问题展开: 1、消息机制的作用? Handler作为消息机制的发起者和终结者,我们看看Handler源码中的注释是如何说的...

fsf_snail的专栏 1129

《数学建模与数学实验》第5版 线性规划 习题3.4

1. 某鸡场有1000只鸡,用动物饲料和谷物混合喂养. 2. 某工厂用A1,A2两台机床加工B1,B2,B3三种不同零件. 3. 某工厂利用两种原料甲、乙生产$A_1、A_2、A_3$三种产品. 4. 每班的护士在值班开始时向病房报到,连续工作8个小时. 5. 某工厂生产 A1 、A2 两种型号的产品 6. 有两个煤厂A,B 7. 某工厂制造三种产品,生产这三种产品需要三种资源 8. 已知某工厂计划生产1,2,3三种产品,各产品需要在ABC设备加工。...

hexiaosi_的博客 2万+

Android Handler消息机制原理最全解读

本文主要详细去解读Android开发中最常使用的Handler,以及使用过程中遇到的各种各样的疑问。 Handler  在Android开发的过程中,我们常常会将耗时的一些操作放在子线程(work thread)中去执行,然后将执行的结果告诉UI线程(main thread),熟悉Android的朋友都知道,UI的更新只能通过Main thread来进行。那么这里就涉及到了如何将 子线程的数据传递...

陈志宝‑天津|Android&Java 全栈开发工程师 1345

基于MOS的防反接电路

防反接电路一般用于电源入口处,在电源反接时,保证电源入口之后的电路不会受到损害。一般在电源电流较小、对1V左右的压降不敏感时可以使用二极管进行防反接。防反接的形式有直接在正极串联二极管(如图1),或使用整流桥的方式(如图2),但这两种方式均存在:1、存在二极管的管压降;2、过大电流时,二极管消耗的功率大,发热严重。这两个问题。 图 1 二极管防反接电路 图 2 整流管防反接电路 1、基于NMO...

qq_42682826的博客 2万+

uniapp(全端兼容) - 超详细接入百度统计功能,给uniapp全平台各端项目引入添加百度统计的插件统计流量详细的步骤教程(提供最新的百度统计源代码,详细的示例代码复制粘贴即可快速搞定!)

uniapp h5 app 使用加入接入百度统计,uniapp百度统计,uniapp详细引入百度统计的教程,uniapp接入百度统计,uniapp如何实现加入百度的统计代码,uniapp怎么植入百度统计详细教程,uniapp如何对接百度统计,uniapp百度统计不生效怎么办,uniapp使用百度统计不生效常见问题,uniapp引入百度统计后没有生效,uniapp h5网页接入百度统计代码后没有统计无效,uniapp最新接入使用百度统计功能,uniapp增加百度统计代码,uniapp app如何接入百度统计,

✅ 精选推荐文章 1万+

安卓消息机制

【Android】消息机制

qq_33512072的博客 1455

Transformer在BEV感知中的统治地位

Transformer在BEV感知中的统治地位 ,人工智能,计算机视觉,大模型,AI,本文围绕 Transformer 在 BEV 感知中的统治地位展开,介绍了 Transformer 的基础原理,如自注意力、多头注意力机制等,以及 BEV 感知的概念、任务与挑战。阐述了 Transformer 在 BEV 感知中的技术优势,包括全局建模、灵活特征融合和长距离依赖捕捉能力,还介绍了典型架构、代码示例及在自动驾驶目标检测等领域的应用案例。同时,评估了其性能,提及优化方法,并展望了与其他技术融合、端到端系统等…

不踩坑,不知道坑有多深;不总结,踩过的坑白踩。 20万+

Android 消息机制的原理及源码解析

一、消息机制概述 1.消息机制的简介 在 Android 中使用消息机制,我们首先想到的就是 Handler。没错, Handler 是Android 消息机制的上层接口。 Handler 的使用过程很简单,通过它可以轻松地将 一个任务切换到 Handler 所在的线程中去执行。通常情况下, Handler 的使用场景就是更新 UI。如下就是使用消息机制的一个简单实例: public class Activity extends android.app.Activity { pri...

陈立的博客 430

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Android 消息机制原理解析

一、概序关于Android消息机制的使用,大家一个想到的就会是在子线程中更新控件,确实,安卓设计出这个机制很大一部分原因是处于这个目的,但是并不是全部。本篇文章,作者也会从源码的角度去分析消息机制的运作方式,希望大家能从文章中了解到消息机制的使用方法以及它为什么能被这样用。二、Android消息机制首先我们来看一下平常使用消息机制的方式:public class MainActivity exten

u010618194的博客 554

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

android handler的机制和原理_Android消息机制的原理及源码解析

提起Android消息机制,想必都不陌生。其中包含三个部分:Handler,MessageQueue以及Looper,三者共同协作,完成消息机制的运行。本篇文章将由浅入深解析Android消息机制的运行原理,先介绍三者之间的协作框架,然后从源码的角度来分析具体的运行机制。一、消息机制概述1.消息机制的简介在Android中使用消息机制,我们首先想到的就是Handler。没错,Handler是And...

weixin_39587238的博客 94

(转)Android 消息机制原理解析

本文转自Android 消息机制原理

forwardto9的专栏 391

Android Handler 消息机制原理解析

欢迎访问我的个人博客 传送门 前言 做过 Android 开发的童鞋都知道,不能在非主线程修改 UI 控件,因为 Android 规定只能在主线程中访问 UI ,如果在子线程中访问 UI ,那么程序就会抛出异常 android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread tha

眼要看远,脚要近迈 693

Android消息机制Handler的实现原理解析

[ Android消息机制Handler的实现原理解析]Android的主线程为什么可以一直存在? 线程是一个动态执行的过程,从产生到死亡包括五个状态:新建、就绪、运行、死亡和堵塞。只要线程没有执行完毕或者没有被其它线程杀死,线程就不会进入死亡状态。Android中的主线程一直存在是因为主线程中一直在监听消息,从而使线程无法被执行完毕。 线程的五种状态: 新建new Thread 当创建Thr

lyl278401555的专栏 5090

android 结束if循环_Android消息机制的原理及源码解析

提起Android消息机制,想必都不陌生。其中包含三个部分:Handler,MessageQueue以及Looper,三者共同协作,完成消息机制的运行。本篇文章将由浅入深解析Android消息机制的运行原理,先介绍三者之间的协作框架,然后从源码的角度来分析具体的运行机制。一、消息机制概述1.消息机制的简介在Android中使用消息机制,我们首先想到的就是Handler。没错,Handler是And...

weixin_32393875的博客 110

抓取android ui原理,Android Handler 消息机制原理解析

欢迎访问我的个人博客 传送门前言做过 Android 开发的童鞋都知道,不能在非主线程修改 UI 控件,因为 Android 规定只能在主线程中访问 UI ,如果在子线程中访问 UI ,那么程序就会抛出异常android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a...

weixin_33603067的博客 158

深入理解Android处理消息机制原理解析

在日常的开发中,Android 的消息机制作为系统运行的根本机制之一,显得十分的重要。  从 Handler 发送消息开始  查看源码,Handler的post、send方法最终都会走到  代码  public final boolean sendMessageDelayed(Message msg, long delayMillis) {       if (delayMillis &lt; ...

小雨点的博客 429

android消息机制 - Handler、Looper原理解析

android的消息机制就是指Handler、MessageQueue和Looper的工作过程。需要传递消息时,由Handler会调用MessageQueue的enqueueMessage方法将消息放入消息队列中,Looper会不断从队列里取消息,取出以后再交给Handler去处理。Handler在创建时要使用当前线程的Looper来构建内部的消息处理系统,所以如果当前线程没有Looper,就会报错

AndroidConqueror的博客 945

Android消息机制使用及原理深度解析

Android消息机制(平时都称为Handler,虽然Handler只是其中的一个类,但是开发者都知道说到Handler时都是指 Android消息机制,所以本文用Handler指代Android消息机制)是Android系统中十分重要的模块,平时开发中经常会使用到,当然也是Android面试官比较喜欢考察的地方。初级开发者一般掌握怎么使用也就够了,中高级开发者是必须要掌握其中的原理的,掌握了其中的原理能更好地使用Handler以及在碰到问题时能快速定位。我最近时间稍显宽裕,所以就认真地看了...

柯汐的博客 455

Android消息机制之Handler原理解析

在平时开发中经常会使用Handler发送消息,那么Handler到底是什么呢? Handler是Android系统提供的一套消息处理机制,通过它可以实现线程间数据传递。 在开发中会将涉及到耗时操作放入子线程中执行,待执行完毕后需要将直接结果更新至主线程,这时就需要用到Handler。当然Handler不仅仅只能将子线程的数据传递至主线程,它可以实现任意两个线程间的通信哦!看完本篇文章,相信你就...

佩琪的铁锤的博客 425
上一篇: 广播静态注册多个action,scheme导致的冲突
下一篇: View的post方法到底干了啥,深入分析Android异步消息处理机制
Ray534
博客等级 码龄12年 2粉丝 2原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值