ActivityThread是什么,是主线程吗?它是如何被创建的,以及它的作用又是什么呢?带着这些问题,我们一起来分析下ActivityThread。

全文分为以下几个部分,大家可根据需求阅读

文章目录

  • ActivityThread是什么
  • ActivityThread对象如何被创建的
    • system_server进程
    • App进程
  • ActivityThread的作用
    • 进程
    • Activity
    • Service
    • BroadcastReceiver
    • ContentProvider
  • 总结

ActivityThread是什么

ActivityThread是应用进程的初始化类,它的main()方法就是应用的入口方法,也就是说应用进程被创建后会调用ActivityThread.main()方法,关于这一点可以参考《Android App进程创建过程分析》中客户端发送创建进程和服务端响应创建进程内容。ActivityThread也是我们常说的主线程,但是这种描述不太准确,ActivityThread不是线程,只不过它是在运行在主线程(main)的main()方法中创建的对象,自然它也是运行在主线程中。只能说ActivityThread是主线程的一部分,但不并能代表主线程。我们从下面的profiler cpu usage图也能看出,ActivityThread.main()方法是在主线程(main)中调用的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N5zsEBak-1634819360670)(./thread_of_activity_thread.png)]

ActivityThread对象如何被创建的

 关于ActivityThread对象创建,分为两种情况:

  • system_server进程创建ActivityThread对象;
  • App进程创建ActivityThread对象;

system_server进程

 关于system_server进程(进程名为system_process)会创建ActivityThread对象,可能大家会有点疑惑,不过system_sever进程中确实存在ActivityThread对象的,这一点我们可以通过AS profiler工具验证。

既然知道system_server进程中存在ActivityThread对象,我们就来看下system_server进程中创建ActivityThread对象的过程。

从上面的时序图我们可以看到:在SystemServer.createSystemContext()方法中会调用ActivityThread静态方法systemMain(),得到ActivityThread对象,这个过程中也会创建Application对象,并调用其onCreate()方法。我们通过源码看下整个过程,首先看下SystemServer.createSystemContext()方法。

//frameworks\base\services\java\com\android\server\SystemServer.java
private void createSystemContext() {//得到ActivityThread对象,ActivityThread activityThread = ActivityThread.systemMain();//为mSystemContext变量赋值mSystemContext = activityThread.getSystemContext();mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);final Context systemUiContext = activityThread.getSystemUiContext();systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
}

该方法比较简单,首先通过ActivityThread静态方法systemMain()得到ActivityThread对象,接着给mSystemContext变量赋值,然后设置Context主题。我们重点看下ActivityThread.systemMain()方法。

//frameworks\base\core\java\android\app\ActivityThread.java
@UnsupportedAppUsage
public static ActivityThread systemMain() {if (!ActivityManager.isHighEndGfx()) {ThreadedRenderer.disable(true);} else {ThreadedRenderer.enableForegroundTrimming();}//创建ActivityThread对象ActivityThread thread = new ActivityThread();//然后调用attach方法,注意传入的两个参数;//第一个参数表示是system_server进程,第二个参数表示system_server进程是第一个被创建的应用类进程。thread.attach(true, 0);return thread;
}/**
* @param system 用于标志是否是system_server进程调用的;
* @param startSeq 表示当前创建的是第几个app进程。
*/
private void attach(boolean system, long startSeq) {sCurrentActivityThread = this;mSystemThread = system;if (!system) {android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",UserHandle.myUserId());RuntimeInit.setApplicationObject(mAppThread.asBinder());final IActivityManager mgr = ActivityManager.getService();try {mgr.attachApplication(mAppThread, startSeq);} catch (RemoteException ex) {throw ex.rethrowFromSystemServer();}//.....省略部分代码......} else {//system_server创建ActivityThread对应else语句android.ddm.DdmHandleAppName.setAppName("system_process",UserHandle.myUserId());try {mInstrumentation = new Instrumentation();mInstrumentation.basicInit(this);ContextImpl context = ContextImpl.createAppContext(this, getSystemContext().mPackageInfo);//创建Application对象,然后调用它的onCreate()方法mInitialApplication = context.mPackageInfo.makeApplication(true, null);mInitialApplication.onCreate();} catch (Exception e) {throw new RuntimeException("Unable to instantiate Application():" + e.toString(), e);}}//.....省略部分代码......
}

在systemMain()方法中会创建ActivityThread对象,然后调用attach(true, 0),true表示是system_server进程,0表示system_server是第一个被创建的应用进程。在attach()方法中会创建Application对象,并调用onCreate方法,Application具体创建过程和生命周期方法调用大家可以参考上面的时序图自己跟下代码。

App进程

 对于普通App进程中会创建ActivityThread对象这一点,想必大家不会有什么疑问。我们同样可以通过AndroidStudio profiler工具验证,比如下面所示的setting应用。

 和system_server进程不同,普通App进程中ActivityThread对象的创建是从ActivityThread.main()方法开始的,我们看下main()方法的具体实现。

public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");AndroidOs.install();CloseGuard.setEnabled(false);//初始化Environment,调用该方法后;Environment类方法(比如getExternalStorageState())才能正确的起作用Environment.initForCurrentUser();// Make sure TrustedCertificateStore looks in the right place for CA certificatesfinal File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());TrustedCertificateStore.setDefaultUserDirectory(configDir);Process.setArgV0("<pre-initialized>");//创建主线程Looper,主线程Looper是不可退出的。Looper.prepareMainLooper();// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.// It will be in the format "seq=114"long startSeq = 0;if (args != null) {for (int i = args.length - 1; i >= 0; --i) {if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {startSeq = Long.parseLong(args[i].substring(PROC_START_SEQ_IDENT.length()));}}}//创建ActivityThread对象,然后调用attach()方法。ActivityThread thread = new ActivityThread();thread.attach(false, startSeq);//将ActivityThread的Handler变量mH赋值给类变量sMainThreadHandler.if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();}if (false) {Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));}// End of event ActivityThreadMain.Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);//进入loop循环,如果Looper中MessageQueue中没有消息,则会一阻塞。Looper.loop();throw new RuntimeException("Main thread loop unexpectedly exited");
}

main()方法主要做了以下几件事:

  • 初始化Environment;
  • 创建主线程Looper;
  • 创建ActivityThread对象,并调用其attach()方法;
  • 调用Looper.loop(),进入循环,阻塞式等待消息。

和systemMain()一样,main()方法也会调用attach()方法,只不过传入的参数不一样,main()方法中第一参数传入的为false,整个流程如下时序图所示:

从时序图中我们可以看出,attach()方法执行过程中会调用ActivityManagerService.attachApplicationLocked()方法,该方法执行过程可分为以下几个步骤:

  • 创建Application对象,并调用其onCreate()生命周期方法;
  • 判断是否需要启动Activity(对应通过start activity 的方式冷启动App);
  • 判断是否需要启动Service(对应通过start service 的方式冷启动App);
  • 判断是否有广播接收者需要接收广播(对应通过send broadcast 的方式冷启动App);

整个过程也很好解释了为什么冷启动一个App时会先调用Application的生命周期方法。我们简单看下ActivityManagerService.attachApplicationLocked()方法。

//ActivityManagerService.java
@GuardedBy("this")
private final boolean attachApplicationLocked(IApplicationThread thread,int pid, int callingUid, long startSeq) {ProcessRecord app;long startTime = SystemClock.uptimeMillis();long bindApplicationTimeMillis;if (pid != MY_PID && pid >= 0) {synchronized (mPidsSelfLocked) {app = mPidsSelfLocked.get(pid);}//省略部分代码......}//省略部分代码......try{//省略部分代码......checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");bindApplicationTimeMillis = SystemClock.elapsedRealtime();mAtmInternal.preBindApplication(app.getWindowProcessController());final ActiveInstrumentation instr2 = app.getActiveInstrumentation();if (app.isolatedEntryPoint != null) {//如果是isolate进程(可通过android:isolatedProcess设置),则不绑定Applicationthread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);} else if (instr2 != null) { //下面两种情况会调用ActivityThread.ApplicationThread.bindApplication()thread.bindApplication(processName, appInfo, providers,instr2.mClass,profilerInfo, instr2.mArguments,instr2.mWatcher,instr2.mUiAutomationConnection, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.isPersistent(),new Configuration(app.getWindowProcessController().getConfiguration()),app.compat, getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, autofillOptions, contentCaptureOptions);} else {thread.bindApplication(processName, appInfo, providers, null, profilerInfo,null, null, null, testMode,mBinderTransactionTrackingEnabled, enableTrackAllocation,isRestrictedBackupMode || !normalMode, app.isPersistent(),new Configuration(app.getWindowProcessController().getConfiguration()),app.compat, getCommonServicesLocked(app.isolated),mCoreSettingsObserver.getCoreSettingsLocked(),buildSerial, autofillOptions, contentCaptureOptions);}if (profilerInfo != null) {profilerInfo.closeFd();profilerInfo = null;}// Make app active after binding application or client may be running requests (e.g// starting activities) before it is ready.app.makeActive(thread, mProcessStats);checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");mProcessList.updateLruProcessLocked(app, false, null);checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();} catch (Exception e) {// todo: Yikes!  What should we do?  For now we will try to// start another process, but that could easily get us in// an infinite loop of restarting processes...Slog.wtf(TAG, "Exception thrown during bind of " + app, e);app.resetPackageList(mProcessStats);app.unlinkDeathRecipient();mProcessList.startProcessLocked(app, new HostingRecord("bind-fail", processName));return false;}// Remove this record from the list of starting applications.mPersistentStartingProcesses.remove(app);if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG_PROCESSES,"Attach application locked removing on hold: " + app);mProcessesOnHold.remove(app);boolean badApp = false;boolean didSomething = false;// 判断是否需要启动Activity,当冷启动某个app的Activity的情况下,就会在此时启动Activity。if (normalMode) {try {didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());} catch (Exception e) {Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);badApp = true;}}// 判断是否需要启动Service,当通过start service的方式冷启动一个app时,会在此时启动serviceif (!badApp) {try {didSomething |= mServices.attachApplicationLocked(app, processName);checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");} catch (Exception e) {Slog.wtf(TAG, "Exception thrown starting services in " + app, e);badApp = true;}}// 判断是否有广播接收者,情况和上面Activity、Service类似。if (!badApp && isPendingBroadcastProcessLocked(pid)) {try {didSomething |= sendPendingBroadcastsLocked(app);checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");} catch (Exception e) {// If the app died trying to launch the receiver we declare it 'bad'Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e);badApp = true;}}// Check whether the next backup agent is in this process...if (!badApp && backupTarget != null && backupTarget.app == app) {if (DEBUG_BACKUP) Slog.v(TAG_BACKUP,"New app is backup target, launching agent for " + app);notifyPackageUse(backupTarget.appInfo.packageName,PackageManager.NOTIFY_PACKAGE_USE_BACKUP);try {thread.scheduleCreateBackupAgent(backupTarget.appInfo,compatibilityInfoForPackage(backupTarget.appInfo),backupTarget.backupMode, backupTarget.userId);} catch (Exception e) {Slog.wtf(TAG, "Exception thrown creating backup agent in " + app, e);badApp = true;}}if (badApp) {app.kill("error during init", true);handleAppDiedLocked(app, false, true);return false;}//省略部分代码......return true;
}

attachApplicationLocked()方法很长,我们只截取了其中的一部分;在这个方法中首先会调用ApplicationThread.bindApplication()方法,在该方法中通过主线程Handler对象H发送绑定Application的消息,在消息处理方法handleBindApplication创建Application对象,并调用其onCreate()生命周期方法。当然在handleBindApplication()方法中不仅仅是创建Application对象和调用其生命周期方法,还包括设置进程的名称、应用data数据存储路径、时间格式等。在之后的流程就是判断是否需要启动Activity、Service、处理广播。

 了解完ActivityThread对象是如何被创建的,我们在来看下它具体有哪些作用。

ActivityThread的作用

进程

  ActivityThread对于App进程来说,它是App的入口。此外ActivityThread还实现了创建主线程Looper、dump应用内存使用情况、获取应用包名等接口;具体内容这里不展开,大家可以自己去看看。我们看看ActivityThread对于四大组件的作用,一句话概括,ActivityThread管理着四大组件的生命周期方法的调用。

Activity

 在之前的《Android Activity启动过程分析》有提到Activity生命周期方法的具体调用过程,所以这里不在赘述。Activity的几个生命周期方法的调用过程如下:

onCreate: ActivityThread.handleLaunchActivity() -> ActivityThread.performLaunchActivity() -> Instrumentation.callActivityOnCreate() -> Activity.performCreate(icicle) -> Activity.onCreate()

onStart: ActivityThread.handleStartActivity() -> ActivityThread.performStart() -> Instrumentation.callActivityOnStart() -> Activity.onStart()

onResume: ActivityThread.handleResumeActivity() -> ActivityThread.performResumeActivity() -> Activity.performResume() -> Instrumentation.callActivityOnResume() -> Activity.onResume()

onPause: ActivityThread.handlePauseActivity() -> ActivityThread.performPauseActivity() -> ActivityThread.performPauseActivityIfNeeded() -> Instrumentation.callActivityOnPause() -> Activity.performPause() -> Activity.onPause()

onStop: ActivityThread.handleStopActivity() -> ActivityThread.performStopActivityInner() -> ActivityThread.callActivityOnStop() -> Activity.performStop() -> Activity.onStop()

onDestory: ActivityThread.handleDestroyActivity() -> ActivityThread.performDestroyActivity() -> Instrumentation.callActivityOnDestroy() -> Activity.performDestroy() -> Activity.onDestroy()

对于Service、BroadcastReceiver以及ContentProvider的生命周期方法调用具体细节,这里也不展开,下次再对她们一一单独讲解,这里只列举调用过程。

Service

onCreate: ActivityThread.scheduleCreateService() -> ActivityThread.handleCreateService() -> Service.onCreate()

onBind(): ActivityThread.scheduleBindService() -> ActivityThread.handleBindService() -> Service.onBind()

onStartCommand: ActivityThread.scheduleServiceArgs() -> ActivityThread.handleServiceArgs() -> Service.onStartCommand()

onDestroy: ActivityThread.scheduleStopService() -> ActivityThread.handleStopService() -> Service.onDestroy()

BroadcastReceiver

onReceive: ActivityThread.ApplicationThread.scheduleReceiver() -> ActivityThread.handleReceiver() -> Receiver.onReceive()

ContentProvider

onCreate: ActivityThread.ApplicationThread.scheduleInstallProvider() -> ActivityThread.handleInstallProvider() -> ActivityThread.installContentProviders() -> ActivityThread.installProvider() -> ContentProvider.attachInfo() -> ContentProvider.onCreate()

总结

 最后我们稍稍总结下

  • ActivityThread类是应用初始化类,它的main()方法是应用的入口方法;
  • ActivityThread不是线程,我们之所以称它为“主线程”,是因为它运行在主线程中;
  • ActivityThread负责创建Application对象以及管理其生命周期方法调用;
  • ActivityThread管理着四大组件的生命周期方法调用;

最后,留给大家一个作业——为什么四大组件的的生命周期方法是在主线程中被调用的?大家可以带着这个问题自己去研究下ActivityThread。另外,关于Activity的启动和App进程的创建可以参考以下的文章

Activity UI显示流程分析

Android Activity启动过程分析

Android App进程创建过程分析

一文读懂ActivityThread相关推荐

  1. 从实验室走向大众,一文读懂Nanopore测序技术的发展及应用

    关键词/Nanopore测序技术    文/基因慧 随着基因测序技术不断突破,二代测序的发展也将基因检测成本大幅降低.理想的测序方法,是对原始DNA模板进行直接.准确的测序,消除PCR扩增带来的偏差, ...

  2. 一文读懂Faster RCNN

    来源:信息网络工程研究中心本文约7500字,建议阅读10+分钟 本文从四个切入点为你介绍Faster R-CNN网络. 经过R-CNN和Fast RCNN的积淀,Ross B. Girshick在20 ...

  3. 福利 | 一文读懂系列文章精选集发布啦!

    大数据时代已经悄然到来,越来越多的人希望学习一定的数据思维和技能来武装自己,虽然各种介绍大数据技术的文章每天都扑面而来,但纷繁又零散的知识常常让我们不知该从何入手:同时,为了感谢和回馈读者朋友对数据派 ...

  4. ​一文读懂EfficientDet

    一文读懂EfficientDet. 今年年初Google Brain团队在 CVPR 2020 上发布了 EfficientDet目标检测模型, EfficientDet是一系列可扩展的高效的目标检测 ...

  5. 一文读懂序列建模(deeplearning.ai)之序列模型与注意力机制

    https://www.toutiao.com/a6663809864260649485/ 作者:Pulkit Sharma,2019年1月21日 翻译:陈之炎 校对:丁楠雅 本文约11000字,建议 ...

  6. AI洞观 | 一文读懂英特尔的AI之路

    AI洞观 | 一文读懂英特尔的AI之路 https://mp.weixin.qq.com/s/E9NqeywzQ4H2XCFFOFcKXw 11月13日-14日,英特尔人工智能大会(AIDC)在北京召 ...

  7. 一文读懂机器学习中的模型偏差

    一文读懂机器学习中的模型偏差 http://blog.sina.com.cn/s/blog_cfa68e330102yz2c.html 在人工智能(AI)和机器学习(ML)领域,将预测模型参与决策过程 ...

  8. 一文读懂AI简史:当年各国烧钱许下的愿,有些至今仍未实现

    一文读懂AI简史:当年各国烧钱许下的愿,有些至今仍未实现 导读:近日,马云.马化腾.李彦宏等互联网大佬纷纷亮相2018世界人工智能大会,并登台演讲.关于人工智能的现状与未来,他们提出了各自的观点,也引 ...

  9. 一文读懂你该了解的5G知识:现在别买5G手机

    来源: 腾讯科技 2019年是中国全力布局5G的一年:三大运营商纷纷搭建基站,手机厂商发布5G手机,部分城市已经开启了5G测试--在电信日这天,腾讯科技联合知乎推出重磅策划,聚焦和5G相关的小知识,精 ...

最新文章

  1. java包装_Java基础之神奇的包装类(一)
  2. docker初体验:docker部署nginx负载均衡集群
  3. 数组, 数组的初始化
  4. 聊一聊IAR的workspace文件组织
  5. weakself的一种写法
  6. SAP Marketing Cloud功能简述(五) : 销售计划管理
  7. 常见的Python解释器,你了解多少?
  8. 打开Word时会出现错误的解决办法
  9. 易语言版{大智慧/分析家/飞狐交易师}DLL插件接口开发模块(beta),自定义股票软件公式扩展函数...
  10. TJA1101汽车网卡调试
  11. IELTS-writing exercise Expository_Text_18
  12. airvideo_如何免费获取Android中的AirVideo功能
  13. PS_BaseUse_红眼擦拭
  14. 牛逼哄哄的富士康老板郭台铭低头了,夏普将向三星供应液晶面板
  15. 股票之四大支撑法则(平台,趋势,均线,缺口)
  16. CVPR 2019 目标检测论文汇总
  17. IMX8MP录像功能测试
  18. 【随手记】共振峰的特性、与音高pitch
  19. Linux安装Nexus3搭建maven私服超详细搭建上传步骤
  20. matlab:栅格地图转化为邻接矩阵

热门文章

  1. war3联机对战原理以及T人挂原理简述
  2. 一劳永逸解决开始菜单运行总以管理员模式进行(cmd总是管理员模式)
  3. 我的周刊(第024期)
  4. python调用企业微信机器人API-自动发送文本、图片与CSV文件3种方式
  5. 学习记录(三)(每日修改)
  6. 深度学习中的动量momentum
  7. SpringCloud 项目搭建
  8. Spring-2.0.0.M3超详细文档(第一弹)
  9. 【产品人生】<提升产品认知>互联网思维与格局
  10. VS编译器、C++、C如何折叠代码