Android 中你碰不到但是很重要的类之ActivityThread

article/2025/11/5 6:08:03

作者:Drummor

通过本文能了解一下内容

1、和系统进程打交道的桥头堡

应用进程起来之后ART(Android Runtime)第一站就是ActivityThread,代码层面上就是ActivityThread的main()方法,是不是很熟悉,爷青回啊,这不就是java的main方法嘛

   public static void main(String[] args) {Looper.prepareMainLooper();ActivityThread thread = new ActivityThread();thread.attach(false, startSeq);sMainThreadHandler = thread.getHandler();Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");}

该方法是一个静态方法,里面做了重要的两件事

  • 创建了让主线程Looper开始工作,并创建了一个Handler
  • 给system_server【递纸条】告诉他联系方式,告诉sytem_servr进程与应用进程取得联系可以通过ApplicationThread这个binder。看下面这个代码
    private void attach(boolean system, long startSeq) {final IActivityManager mgr = ActivityManager.getService();mgr.attachApplication(mAppThread, startSeq);//调用远端的binder}
  • 通过ActivityManager.getService()拿到system_server进程的binder,然后把mAppThread binder传递过去。mAppThreadApplicationThread的一个对象,是ActivityThread的一个内部类。
  • 取得联系后的第一站创建Applicaiton。
   private class ApplicationThread extends IApplicationThread.Stub {@Overridepublic final void bindApplication() {sendMessage(H.BIND_APPLICATION, data);}
  • 接下来就是H主线程的Hanlder,调用handleBindApplication
 private void handleBindApplication(AppBindData data) {Application app;data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo, isSdkSandbox);//内部创建LoadedApkapp = data.info.makeApplicationInner(data.restrictedBackupMode, null);//内部创建Applicaiton对象,调用onCreate()方法installContentProviders(app, data.providers); //cotentprovider初始化mInstrumentation.callApplicationOnCreate(app);//调用onCreate()方法}
  • 这里找到了为什么使用ContentProvider能够实现初始化,构建的时候会创建ContenProvider。
 public Activity newActivity(ClassLoader cl, String className,Intent intent)throws InstantiationException, IllegalAccessException,ClassNotFoundException {String pkg = intent != null && intent.getComponent() != null? intent.getComponent().getPackageName() : null;return getFactory(pkg).instantiateActivity(cl, className, intent);//加载创建Activity}

  • IActivityManager(binder):应用进程和SystemServer进程打交道的时候。
  • AppliactionThread(binder):SystemServer进程与应用进程通信。

2、为什么使用ContentProvider可以实现初始化

 private void handleBindApplication(AppBindData data) {Application app;data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo, isSdkSandbox);//内部创建LoadedApkapp = data.info.makeApplicationInner(data.restrictedBackupMode, null);//内部创建Applicaiton对象,调用onCreate()方法installContentProviders(app, data.providers); //cotentprovider初始化mInstrumentation.callApplicationOnCreate(app);//调用onCreate()方法}

上一段分析时已经找打了答案,应用进程被拉起来之后,在创建Application对象调用attachBaseContext()和onCreate()方法之间会调用ContentProvider的onCreate()方法这也是很多第三方SDK使用该特性实现初始化的原理。

3、Activity是什么时候开始渲染的

  public void handleResumeActivity() {performResumeActivity(r, finalStateRequest, reason)//调用Activity onResumefinal Activity a = r.activity;View decor = r.window.getDecorView();ViewManager wm = a.getWindowManager();a.mWindowAdded = true;wm.addView(decor, l);}

ActivityThread.javahandleResumeActivity()有这样一段代码,我们可以得出结论,Activity渲染的起点是在 onResume阶段,在onResume阶段会把decorView交给WindowManager开始执行渲染。

4、原来还可以监控组件的生命周期

class H extends Handler {public static final int RECEIVER                = 113; //广播接收者@UnsupportedAppUsagepublic static final int CREATE_SERVICE          = 114;//Service创建public static final int INSTALL_PROVIDER        = 145;//ContentProviderpublic static final int RELAUNCH_ACTIVITY = 160; //Activity启动public void handleMessage(Message msg) {if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));switch (msg.what) {case BIND_APPLICATION:Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");AppBindData data = (AppBindData)msg.obj;handleBindApplication(data);Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);break;case RECEIVER:handleReceiver((ReceiverData)msg.obj);break;case CREATE_SERVICE:handleCreateService((CreateServiceData)msg.obj);break;case BIND_SERVICE:handleBindService((BindServiceData)msg.obj);break;case RELAUNCH_ACTIVITY:handleRelaunchActivityLocally((IBinder) msg.obj);break;}}
}

系统进程(system_server)指挥应用进程组件生命周期的第一站其实就在ActivityThread这里,交给H对象其实是主线程的Handler来分发处理,如上。我们可以反射拿到这一信息,可以监控到主线程对于这些组件调度的信息,这一信息对我们监控排查ANR很有帮助。

5 、SharedPreference被声讨的根源

 private void handleStopService(IBinder token) {QueuedWork.waitToFinish();      }public void handlePauseActivity(){QueuedWork.waitToFinish(); }public void handleStopActivity(){QueuedWork.waitToFinish(); }
public void handleServiceArgs(){QueuedWork.waitToFinish(); 
}

ActivityThread的以上方法里会调用 QueuedWork.waitToFinish(); 该代码会堵塞主线程执行等待SP的写入操作。这也是SP造成ANR的根源。

稍微展开点

   public static void waitToFinish() {while (true) {Runnable finisher;synchronized (sLock) {finisher = sFinishers.poll();}if (finisher == null) {break;}finisher.run();}} }

waitToFinish()方法里有这样一段代码,sFinishers是一个List里面是存放的SP写入操作,会在SP执行commit和apply的时候放入进来。字节跳动团队就是在此处hook了使其poll()方法永远放回空,来杜绝此处产生的ANR。

7 、结

通过阅读ActivityThread的源码我们能在其中获取很多有用的知识。系统进程和应用进程通信的桥梁,Activity真正渲染的起始点,ContentProvider能实现SDK自动初始化的原理等都在ActivityThread看到他们的影子。


所以我们还更需要了解Framework 底层原理+具备性能优化的能力,这样才能体现出你的价值。因此在这为大家整合了这些:《Android 性能优化核心知识点手册》和《Android Framework核心知识点手册》,供大家进行复习参考学习:

《Android 性能调优核心笔记汇总》:https://qr18.cn/FVlo89

《Android 性能监控框架》:https://qr18.cn/FVlo89

《Android Framework核心知识点手册》:https://qr18.cn/AQpN4J

  1. 开机Init 进程
  2. 开机启动 Zygote 进程
  3. 开机启动 SystemServer 进程
  4. Binder 驱动
  5. AMS 的启动过程
  6. PMS 的启动过程
  7. Launcher 的启动过程
  8. Android 四大组件
  9. Android 系统服务 - Input 事件的分发过程
  10. Android 底层渲染 - 屏幕刷新机制源码分析
  11. Android 源码分析实战


http://chatgpt.dhexx.cn/article/fpqouGQ9.shtml

相关文章

浅析ActivityThread#main()方法和生命周期事务处理(代码基于Android-12)

浅析ActivityThread#main()方法和生命周期事务处理(代码基于Android-12) 问题: Activity、Application的onCreate()在哪被调用的? ContentProvider为什么比Application先创建? Activity#attach()在哪里被调用的&#…

Android中的ActivityThread和ApplicationThread

一:ActivityThread和ApplicationThread 1.ActivityThread:主线程、UI线程,程序的入口(main函数),不是线程是运行在主线程中的一个对象 主要的成员变量如下: mActivities、mServices和mProvide…

一文读懂ActivityThread

ActivityThread是什么,是主线程吗?它是如何被创建的,以及它的作用又是什么呢?带着这些问题,我们一起来分析下ActivityThread。 全文分为以下几个部分,大家可根据需求阅读 文章目录 ActivityThread是什么Act…

Android ActivityThread(主线程或UI线程)简介

1. ActivityThread功能 它管理应用进程的主线程的执行(相当于普通Java程序的main入口函数),并根据AMS的要求(通过IApplicationThread接口,AMS为Client、ActivityThread.ApplicationThread为Server)负责调度和执行activities、broa…

ActivityThread的理解和APP的启动过程

ActivityThread的理解和APP的启动过程 ActivityThreadActivityThread的初始化主线程Looper的初始化主线程Handler的初始化ApplicationThread及Activity的创建和启动 APP的启动系统的启动过程APP的启动过程APP启动过程的部分代码思考 总结 ActivityThread ActivityThread就是我…

validate中remote返回函数中+号导致submitHandler无法执行

validate中remote返回函数中号导致submitHandler无法执行 这是2017年以来我遇到的最无语的bug,现在暂时还没想到原因,但是这个错误真的很无语。 这是我的validate中rule的定义,其中 new Date; 采用至慕课网上validate插件视频中的例子。 rul…

jQuery(六)插件、Validate验证提交表单、submitHandler、更改错误信息显示的位置、required、Validator、内置验证方式表、validate ()的可选项汇总

jQuery(六)插件、Validate验证提交表单、submitHandler、更改错误信息显示的位置、required、Validator、内置验证方式表、validate ()的可选项汇总 文章目录 jQuery(六)插件、Validate验证提交表单、submitHandler、更改错误信息…

ajax post 不起作用,jQuery验证submitHandler在$ .ajax post表单数据中不起作用

我使用$.ajax发送数据并使用jQuery验证插件进行验证,如下所示: Send JS: jQuery(document).ready(function ($) { $(#myform).validate({ rules: { name: { required: true, rangelength: [4, 20], }, }, submitHandler: function (form) { $…

FileReader()用法

FileReader()用法HTML5定义了FileReader作为文件API的重要成员用于读文件,根据W3C的定义,FileReaderr接口提供了读取文件的方法和包含读取 结果的事件模型。 FileReader的方法使用比较简单,可以按照以下步骤创建FileReader对象并调用其他的方…

read/write/fsync与fread/fwrite/fflush的关系和区别

read/write/fsync: 1. linux底层操作; 2. 内核调用, 涉及到进程上下文的切换,即用户态到核心态的转换,这是个比较消耗性能的操作。 fread/fwrite/fflush: 1. c语言标准规定的io流操作,建立…

FileReader详解

我在Google Chrome Web Store上发布了一个案例hahaOCR,该扩展程序可以帮助用户识别出图片中的文字信息,并以文本形式显示,大家可以在chrome网上应用商店中找到我发布的应用程序,如图所示: 图1 - hahaOCR 该扩展程序支持…

f.readlines()

f.readlines() ftext open(1299_wangyifei_edit.pinyin, r, encodingutf-8)lines ftext.readlines()print("lines",lines)l ftext.readlines()print("l",l)输出结果: 原因: readlines() 方法用于读取所有行(直到结束符 EOF)并返…

FileReader的用法

FileReader是一种异步文件读取机制,结合input:file可以很方便的读取本地文件。 input:file input的file类型会渲染为一个按钮和一段文字。点击按钮可打开文件选择窗口,文字表示对文件的描述(大部分情况下为文件名);…

【原创】通过 ioctl + FIONREAD 判定数据可读

【原创】通过 ioctl FIONREAD 判定数据可读 摩云飞 2016-05-12 09:57:51 浏览470 评论0 libevent ioctl FIONREAD 摘要: 在排查业务 bug 的过程中,看到如下两种输出信息: TCP 连接正常情况下,进行数据读取 14:00:38 epoll_ctl…

fread函数详解

文章迁移: fread函数详解 - 码到城攻fread函数详解,C函数使用注意事项,freadhttps://www.codecomeon.com/posts/93/ 函数原型: size_t fread( void *buffer, size_t size, size_t count, FILE *stream ) buf…

SQLSTATE: Insert value list does not match column list: 1136 Column count doesn‘t match value count

使用thinkphp5的insertAll的批量新增函数,提示SQLSTATE[21S01]: Insert value list does not match column list: 1136 Column count doesnt match value count at row 2 其意思就是:在第二行数据开始,插入的,每行数据的值的个数和…

Column-Stores vs. Row-Stores: How Different Are They Really

概述 从论文的标题可以看出这篇论文不是陈述一种新的技术、架构,而更偏议论文一点,它主要的目的在于搞清楚对于分析类的查询为什么Column-Store比Row-Store好那么多?好在哪里?一般认为原因是: 分析类查询往往只查询一个表里面很少…

Android应用开发之( TableLayout中stretchColumns、shrinkColumns的用法)

从字面上来看&#xff0c;TableLayout也比较简单&#xff0c;关键是要对相关的属性要熟悉&#xff0c;先看一个简单的例子&#xff08;后面为效果图&#xff09;&#xff1a; <?xml version"1.0" encoding"utf-8"?> <TableLayout xmlns:android…

CollenctionList

1.Collection集合 1.1集合体系结构【记忆】 集合类的特点 提供一种存储空间可变的存储模型&#xff0c;存储的数据容量可以随时发生改变 集合类的体系图 1.2Collection集合概述和基本使用【应用】 Collection集合概述 是单例集合的顶层接口&#xff0c;它表示一组对象&#xff…

输入界面,关于stretchColumns和selectAllOnFocus的属性设置

这是整个TableLayout的代码&#xff1a; <TableLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools"http://schemas.android.com/tools"android:orientation"vertical"android:layout_width"fill_parent&qu…