当前位置: 首页 > ai >正文

Android 生命周期函数调用原理

工作原理详解

1. 消息的源头:系统服务(通过 Binder 线程)
  • 当 AMS 决定要回调一个生命周期方法(如 onCreate)时,它并不会直接调用你的 Activity 方法
  • 它会通过 Binder IPC,向你的应用进程发送一个指令。这个指令最终会调用到 ActivityThread 的内部类 ApplicationThread 的对应方法(如 scheduleLaunchActivity
2. 消息的封装和投递(ApplicationThread -> H)
  • ApplicationThread 的方法运行在 Binder 线程池中的某个线程上,而不是主线程
  • 为了切换到主线程执行,这些方法会做一件事:将客户端(如 AMS)的请求封装成一个 Message,然后发送给主线程的 Handler
  • 这个 Handler 就是 ActivityThread 中的内部类 H(继承自 Handler
  • 例如,在 scheduleLaunchActivity 中:
    // 这运行在Binder线程
    public final void scheduleLaunchActivity(...) {...// 1. 封装信息ActivityClientRecord r = new ActivityClientRecord(...);// 2. 发送消息到主线程队列sendMessage(H.LAUNCH_ACTIVITY, r);
    }
    sendMessage 方法最终会调用 H 的 sendMessage 方法,将 H.LAUNCH_ACTIVITY 这个消息和包含所有数据的 ActivityClientRecord 对象放入主线程的 MessageQueue 中
3. 消息的处理(H 在主线程处理)
  • 主线程的 Looper 一直在无限循环 Looper.loop(),不断地从 MessageQueue 中取出 Message
  • 取出的 Message 会分发给它的目标 Handler,也就是 H 来处理
  • H 的 handleMessage(Message msg) 方法是一个巨大的 switch 语句,根据 msg.what(即消息类型,如 LAUNCH_ACTIVITYRESUME_ACTIVITYPAUSE_ACTIVITY)来执行不同的操作
    class H extends Handler {public static final int LAUNCH_ACTIVITY = 100;public static final int RESUME_ACTIVITY = 107;public static final int PAUSE_ACTIVITY = 101;// ... 很多其他消息类型public void handleMessage(Message msg) {switch (msg.what) {case LAUNCH_ACTIVITY:handleLaunchActivity((ActivityClientRecord) msg.obj, ...);break;case RESUME_ACTIVITY:handleResumeActivity((ActivityClientRecord) msg.obj, ...);break;case PAUSE_ACTIVITY:handlePauseActivity((ActivityClientRecord) msg.obj, ...);break;// ... 处理其他消息}}
    }
4. 最终回调到 Activity
  • 在 H 的 handleLaunchActivityhandleResumeActivity 等方法中,会执行一系列复杂的逻辑,但最终都会直接调用到 Activity 的对应生命周期方法
  • 例如,在 handleLaunchActivity 中:
    private void handleLaunchActivity(ActivityClientRecord r, ...) {...// 1. performLaunchActivity 会完成Activity对象的创建、Context的绑定、Application的attach等Activity activity = performLaunchActivity(r, customIntent);...if (activity != null) {...// 2. 紧接着调用 handleResumeActivityhandleResumeActivity(...);}
    }private void handleResumeActivity(...) {...// 最终会调用到 Activity 的 onResume 方法performResumeActivity(...);
    }// performResumeActivity 内部简化逻辑:
    final Instrumentation.ActivityResult result = activity.performResume();
    // activity.performResume() 内部会调用:
    // mInstrumentation.callActivityOnResume(this);
    // 而 callActivityOnResume 内部就是直接调用:
    // activity.onResume();

画面绘制(View Drawing)也是如此

画面绘制的请求同样是通过消息机制驱动的:

  1. 触发绘制: 当 Activity 变为可见、View 内容发生变化(如 setText())、或用户触摸屏幕时,ViewRootImpl 会请求安排一次绘制流程
  2. 发送消息: ViewRootImpl.scheduleTraversals() 会向主线程的 MessageQueue 提交一个异步消息(通常是一个 Runnable 任务,类型为 TraversalRunnable
  3. 处理消息: 主线程的 Looper 取出这个任务并执行
  4. 执行绘制: 在这个 Runnable 的 run() 方法中,会调用 doTraversal(),继而执行著名的“View 绘制三部曲”:measure()layout()draw()。这一切都发生在主线程上

总结

系统回调类型消息来源 (Binder调用)对应的 H 消息类型最终处理的方法
Activity 生命周期ApplicationThread.scheduleXxxActivity()LAUNCH_ACTIVITYRESUME_ACTIVITYPAUSE_ACTIVITY 等Activity.onCreate()onResume()onPause() 等
Service 生命周期ApplicationThread.scheduleXxxService()CREATE_SERVICEBIND_SERVICESERVICE_ARGS 等Service.onCreate()onBind()onStartCommand() 等
广播接收 (Broadcast)ApplicationThread.scheduleReceiver()RECEIVERBroadcastReceiver.onReceive()
画面绘制 (UI Update)ViewRootImpl.scheduleTraversals()(通常是一个 Runnable 任务)View.measure()layout()draw()

因此,主线程的 Looper 和 Handler (H) 是整个应用进程的“心脏”和“中枢神经系统”。所有来自系统或其他线程的事件,都被转化为消息,由它按顺序、串行地分发给正确的组件进行处理,从而保证了线程安全。这也是为什么不能在主线程执行耗时操作的原因——它会阻塞消息队列,导致生命周期回调、界面绘制等所有消息都无法被及时处理,造成应用卡顿甚至 ANR

http://www.xdnf.cn/news/20035.html

相关文章:

  • 《计算机网络安全》实验报告一 现代网络安全挑战 拒绝服务与分布式拒绝服务攻击的演变与防御策略(3)
  • 2025年数学建模国赛参考论文发布
  • 从碎片化到一体化:Java分布式缓存的“三级跳”实战
  • Spring Security 深度学习(六): RESTful API 安全与 JWT
  • 服务器IP暴露被攻击了怎么办?
  • 微算法科技 (NASDAQ:MLGO)利用量子密钥分发QKD技术,增强区块链系统的抗攻击能力
  • 自动化运维-ansible中对roles的创建与使用
  • 数据无言,网关有声 耐达讯自动化RS485转Profinet让千年液位数据“开口说话”
  • 在VSCode中更新或安装最新版的npx和uv工具
  • 数码视讯TR100-OTT-G1_国科GK6323_安卓9_广东联通原机修改-TTL烧录包-可救砖
  • 容器的定义及工作原理
  • 【华为Mate XTs 非凡大师】麒麟芯片回归:Mate XTs搭载麒麟9020,鸿蒙5.1体验新境界
  • Java 21 虚拟线程微服务进阶实战:2 个企业级场景源码 + 底层调度原理 + 性能调优指南
  • 艾克斯图片转换器,不只图片压缩
  • 音响皇帝BO,牵手全球第一AR眼镜雷鸟,耳机党坐不住了?
  • Kafka 内存池MemoryPool 设计
  • 海盗王64位dx9客户端修改篇之五
  • 别再手工缝合API了!开源LLMOps神器LMForge,让你像搭积木一样玩转AI智能体!
  • 《sklearn机器学习——回归指标1》
  • Linux中的fork详解
  • 好看的背景颜色 uniapp+小程序
  • vue3+ts导出PDF
  • 力扣55:跳跃游戏
  • 每周资讯 | 中国游戏市场将在2025年突破500亿美元;《恋与深空》收入突破50亿元
  • 52核心52线程,Intel下一代CPU憋了个大的
  • uni-app 项目 iOS 上架踩坑经验总结 从证书到审核的避坑指南
  • 一文从零部署vLLM+qwen0.5b(mac本地版,不可以实操GPU单元)
  • 为什么要用VR全景?5个答案告诉你
  • 用户眼中的VR自来水厂之旅
  • 【Android】Room数据库的使用