深入理解Android消息处理系统——Looper、Handler、Thread

Android Camera2 openCamera流程详解(1) 本文用Android 11 的代码进行梳理。 Android Camera2 open Camera的接口为CameraManager的openCamera函数,如下: frameworks/base/core/java/android/hardware/camera2/CameraManager.java 648 @RequiresPermission(android.Manifest.permission.CAMERA) 649 public void openCamera(@Non 阅读详情

 

熟悉Windows编程的朋友可能知道Windows程序是消息驱动的,并且有全局的消息循环系统。而Android应用程序也是消息驱动的,按道理来说也应该提供消息循环机制。实际上谷歌参考了Windows的消息循环机制,也在Android系统中实现了消息循环机制。Android通过Looper、Handler来实现消息循环机制,Android消息循环是针对线程的(每个线程都可以有自己的消息队列和消息循环)。本文深入介绍一下Android消息处理系统原理。

    Android系统中Looper负责管理线程的消息队列和消息循环,具体实现请参考Looper的源码。 可以通过Loop.myLooper()得到当前线程的Looper对象,通过Loop.getMainLooper()可以获得当前进程的主线程的Looper对象。

    前面提到Android系统的消息队列和消息循环都是针对具体线程的,一个线程可以存在(当然也可以不存在)一个消息队列和一个消息循环(Looper),特定线程的消息只能分发给本线程,不能进行跨线程,跨进程通讯。但是创建的工作线程默认是没有消息循环和消息队列的,如果想让该线程具有消息队列和消息循环,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。如下例所示:

  class LooperThread extends Thread {
      public Handler mHandler;

      public void run() {
          Looper.prepare();

          mHandler = new Handler() {
              public void handleMessage(Message msg) {
                  // process incoming messages here
              }
          };

          Looper.loop();
      }
  }这样你的线程就具有了消息处理机制了,在Handler中进行消息处理。

     Activity是一个UI线程,运行于主线程中,Android系统在启动的时候会为Activity创建一个消息队列和消息循环(Looper)。详细实现请参考ActivityThread.java文件。

     Handler的作用是把消息加入特定的(Looper)消息队列中,并分发和处理该消息队列中的消息。构造Handler的时候可以指定一个Looper对象,如果不指定则利用当前线程的Looper创建。详细实现请参考Looper的源码。

     Activity、Looper、Handler的关系如下图所示:

message

     一个Activity中可以创建多个工作线程或者其他的组件,如果这些线程或者组件把他们的消息放入Activity的主线程消息队列,那么该消息就会在主线程中处理了。因为主线程一般负责界面的更新操作,并且Android系统中的weget不是线程安全的,所以这种方式可以很好的实现Android界面更新。在Android系统中这种方式有着广泛的运用。

     那么另外一个线程怎样把消息放入主线程的消息队列呢?答案是通过Handle对象,只要Handler对象以主线程的Looper创建,那么调用Handler的sendMessage等接口,将会把消息放入队列都将是放入主线程的消息队列。并且将会在Handler主线程中调用该handler的handleMessage接口来处理消息。

     这里面涉及到线程同步问题,请先参考如下例子来理解Handler对象的线程模型:

1、首先创建MyHandler工程。

2、在MyHandler.java中加入如下的代码:

package com.simon;

import android.app.Activity;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.os.Handler;

public class MyHandler extends Activity {
    static final String TAG = "Handler";
    Handler h = new Handler(){
        public void handleMessage (Message msg)
        {
            switch(msg.what)
            {
            case HANDLER_TEST:
                Log.d(TAG, "The handler thread id = " + Thread.currentThread().getId() + "/n");
                break;
            }
        }
    };

    static final int HANDLER_TEST = 1;
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Log.d(TAG, "The main thread id = " + Thread.currentThread().getId() + "/n");

        new myThread().start();
        setContentView(R.layout.main);
    }

    class myThread extends Thread
    {
        public void run()
        {
            Message msg = new Message();
            msg.what = HANDLER_TEST;
            h.sendMessage(msg);
            Log.d(TAG, "The worker thread id = " + Thread.currentThread().getId() + "/n");
        }
    }
}在这个例子中我们主要是打印,这种处理机制各个模块的所处的线程情况。如下是我的机器运行结果:

09-10 23:40:51.478: DEBUG/Handler(302): The main thread id = 1
09-10 23:40:51.569: DEBUG/Handler(302): The worker thread id = 8
09-10 23:40:52.128: DEBUG/Handler(302): The handler thread id = 1我们可以看出消息处理是在主线程中处理的,在消息处理函数中可以安全的调用主线程中的任何资源,包括刷新界面。工作线程和主线程运行在不同的线程中,所以必须要注意这两个线程间的竞争关系。

     上例中,你可能注意到在工作线程中访问了主线程handler对象,并在调用handler的对象向消息队列加入了一个消息。这个过程中会不会出现消息队列数据不一致问题呢?答案是handler对象不会出问题,因为handler对象管理的Looper对象是线程安全的,不管是加入消息到消息队列和从队列读出消息都是有同步对象保护的,具体请参考Looper.java文件。上例中没有修改handler对象,所以handler对象不可能会出现数据不一致的问题。

     通过上面的分析,我们可以得出如下结论:

1、如果通过工作线程刷新界面,推荐使用handler对象来实现。

2、注意工作线程和主线程之间的竞争关系。推荐handler对象在主线程中构造完成(并且启动工作线程之后不要再修改之,否则会出现数据不一致),然后在工作线程中可以放心的调用发送消息SendMessage等接口。

3、除了2所述的hanlder对象之外的任何主线程的成员变量如果在工作线程中调用,仔细考虑线程同步问题。如果有必要需要加入同步对象保护该变量。

4、handler对象的handleMessage接口将会在主线程中调用。在这个函数可以放心的调用主线程中任何变量和函数,进而完成更新UI的任务。

5、Android很多API也利用Handler这种线程特性,作为一种回调函数的变种,来通知调用者。这样Android框架就可以在其线程中将消息发送到调用者的线程消息队列之中,不用担心线程同步的问题。

     深入理解Android消息处理机制对于应用程序开发非常重要,也可以让你对线程同步有更加深刻的认识。以上是最近Simon学习Android消息处理机制的一点儿总结,如有错误之处请不吝指教。

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/dywe_ddm/archive/2010/10/10/5930948.aspx

3.4 ISIS和OSPF之间路由引入 通过以上输出可以看到OSPF的路由引入到了IS-IS中。通过以上输出可以看到ISIS的路由没有传递给OSPF。通过以上输出可以看到OSPF的路由没有传递给ISIS。通过以上输出可以看到ISIS的路由被引入进了OSPF。掌握在IS-IS中引入OSPF路由的方法。掌握在OSPF中引入IS-IS路由的方法。图3-3:ISIS和OSPF之间路由引入。在R3上把ISIS的路由引入到OSPF。OSPF引入外部路由的缺省度量值为1。在R3上把OSPF的路由引入到ISIS。引入的外部路由类型为Type2。 阅读详情

相关推荐

头歌操作系统 课堂练习4.2:页式内存管理 答案 无解析

头歌操作系统 课堂练习4.2:页式内存管理 答案 无解析

kercii的博客 1万+

Android下的多线程

在Android下面也有多线程的概念,在C/C++中,子线程可以是一个函数,一般都是一个带有循环的函数,来处理某些数据,优先线程只是一个复杂的运算过程,所以可能不需要while循环,运算完成,函数结束,线程就销毁。对于那些需要控制的线程,一般我们都是和互斥锁相互关联,从而来控制线程的进度,一般我们创建子线程,一种线程是很常见的,那就是带有消息循环的线程。 消息循环是一个很有用的线程方式,曾经自己...

wghjay的专栏 333

别再死磕V1了!手把手教你用WPS Web Office V3 SDK快速集成(附Java Demo避坑指南)

本文详细介绍了如何从WPS Web Office V1迁移到V3版本,重点讲解了V3在性能、安全性和扩展性上的优势,以及Java开发者如何快速集成V3 SDK。文章包含核心功能实现、高级功能适配(如Solon框架)和常见问题排查指南,帮助开发者高效完成迁移并避免常见陷阱。

weixin_27215337的博客 335

Handler一定要在主线程实例化吗?new Handler()和new Handler(Looper.getMainLooper())的区别

一个帖子的整理 一个帖子的整理: Handler一定要在主线程实例化吗?new Handler()和new Handler(Looper.getMainLooper())的区别 如果你不带参数的实例化:Handler handler = new Handler();那么这个会默认用当前线程的looper 一般而言,如果你的Handler是要来刷新操作UI

thanklife的专栏 5万+

目标检测数据集 第069期-基于yolo标注格式的玻璃清洁状态检测数据集(含免费分享)

但这类技术的落地,离不开大量标注规范、场景丰富的数据集作为算法训练的支撑,玻璃清洁状态检测数据集的出现,正是为了满足这一市场与技术需求。在高校与科研机构的计算机视觉研究中,该数据集可作为基础研究素材,用于探索物体状态识别的算法优化方向,比如针对玻璃这类透明物体的检测算法改进,或是小样本场景下的状态识别研究。通过摄像头采集车窗、挡风玻璃的图像,算法自动检测玻璃清洁度,若识别到脏污影响视线,及时提醒运维人员清洁,避免因玻璃脏污引发的安全事故,提升交通出行的安全性。

深度学习算法工程师,专注于前沿算法研究与实战应用。在这里,我将分享深度学习领域的实战经验、优质数据集资源以及最新论文解读与精度分析,旨在与广大技术爱好者共同探索人工智能的奥秘,助力技术成长与创新。 128

死区补偿---学习笔记

最近调试中发现,死区补偿对电流谐波和电流带宽影响挺大,于是对死区补偿产生浓厚兴趣,找来几篇文章粗读并做一下笔记。 传统做法 无非就是根据电流方向补偿,假如svpwm计算出的A相理论导通实践为T1,死区时间是Td,则实际导通时间T = T1-Td(when ia >0 ),于是在svpwm计算出的导通时间T1的基础上加上Td。这样经过PWM模块后,实际的导通时间即为T1. 但存在两个难点(个人总结): 1,受电流检测精度影响,尤其是在过零点检测困难。 2,真实的二极管导通需要一定电压,并非..

圆桌骑士的博客 2万+

Android Handler Message多线程实例

什么是Handler  handler通俗讲就是在各个进程之间发送数据的处理对象。在任何进程中,只要获得了另一个进程的handler则可以通过 handler.sendMessage(message)方法向那个进程发送数据。基于这个机制,我们在处理多线程的时候可以新建一个thread,这 个thread拥有UI线程中的一个handler。当thread处理完一些耗时的操作后通过传递过来的ha

把握自己。 1818

半导体功率器件IGBT工艺全流程

本文概述了功率器件IGBT(绝缘栅双极型晶体管)的关键制造流程。主要工艺包括:基板制备、离子注入(B+/P+/P+FS层)、绝缘膜形成与加工(CVD沉积及刻蚀)、沟槽刻蚀、电极形成(Emitter和Collector)等步骤。通过离子注入、化学气相沉积和物理气相沉积等半导体工艺,依次完成器件各功能层的构建,最终形成具备高功率特性的IGBT器件。该流程体现了功率半导体制造中典型的掺杂、薄膜沉积和图形化工艺技术。

750

looper.java_【转】深入理解Android消息处理系统——Looper、Handler、Thread

熟悉Windows编程的朋友可能知道Windows程序是消息驱动的,并且有全局的消息循环系统。而Android应用程序也是消息驱动的,按道理来说也应该提供消息循环机制。实际上谷歌参考了Windows的消息循环机制,也在Android系统中实现了消息循环机制。Android通过Looper、Handler来实现消息循环机制,Android消息循环是针对线程的(每个线程都可以有自己的消息队列和消息循环...

weixin_31577315的博客 201

数控弯管机xyz转换ybc的算法_数控弯管机技术的更新和应用.pdf

您所在位置:网站首页 > 海量文档&nbsp>&nbsp汽车/机械/制造&nbsp>&nbsp机械/模具设计数控弯管机技术的更新和应用.pdf3页本文档一共被下载:次,您可全文免费在线阅读后下载本文档。 下载提示1.本站不保证该用户上传的文档完整性,不预览、不比对内容而直接下载产生的反悔问题本站不予受理。2.该文档所...

weixin_31493101的博客 1520

环境配置与基础教程:2026大厂标准:使用 DVC (Data Version Control) 实现 YOLO 数据集版本控制全链路管理

本文介绍了使用DVC 3.0对YOLO数据集进行全链路版本控制的方法。主要内容包括: DVC 3.0的核心增强:内容块级缓存去重、并行云传输、AI智能体元数据跟踪等新特性,可显著提升YOLO数据集管理效率。 环境配置:详细说明DVC 3.0的安装步骤、项目初始化方法以及远程存储配置方案(支持S3、GCS、Azure等多种存储后端)。 目录结构规范:提供符合大厂MLOps标准的项目目录结构设计。 实战操作: 原始数据版本化 多格式标注数据版本控制 版本切换方法 优势说明:DVC通过哈希指针机制管理大型数据集,

ZXSXJ的博客 148
上一篇: Android在中国的发展及就业前景解析
下一篇: Android消息处理机制:Handler Thread Message Looper []
Linux先生
博客等级 码龄20年 97粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值