Android Activity启动过程一:从Intent到Activity创建

关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。
专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。

目录

  • 一、概览
  • 二、应用内启动源码流程 (startActivity)
    • 2.1 startActivity()
    • 2.2 startActivityAsUser()
    • 2.3 startActivityUnchecked()
    • 2.4 resumeFocusedStackTopActivityLocked()
    • 2.5 startSpecificActivityLocked -> realStartActivityLocked()
  • 三、 Activity实例化过程
  • 四、 setContentView
  • 五、 后续生命周期
  • 六、 推荐阅读

在这里插入图片描述

学习前,建议有相关知识储备:
【Android 基础】 应用(Application)启动流程

通过本文你可以学习到Activity启动流程。

一、概览

Activity 是 android 四大组件之一,很有必要知道它的启动过程,我们在上一篇文章中介绍了 APP的启动流程,里面大概讲到了Activity的
启动流程,在本文中,我们系统的再总结一下,当成一个记录。

Activity 的启动方式我们讲有两种,一种是在应用内部启动,另一种是外部启动,比如Launcher;

  • 应用内启动
    通过 startActivity、startActivityForResult等方式来启动 Activity

其流程我们总结下:

1、调用 Activity 的 startActivity 方法来启动目标 Activity
2、接着就会调用到 Instrunmentation 的 execStartActivity 方法,然后调用到 AMS 的 startActivity 中去
3、调用到 AMS 中后,会执行到ActivityStarter 的 execute 方法,接着就会进行一些校验和判断权限,包括进程检查,intent检查,权限检查、是否启用新栈等
4、所有的信息存储在ActivityRecord中,ActivityRecord是Activity在system_server进程中的镜像,Activity实例与ActivityRecord实例一一对应。ActivityRecord用来存储Activity的信息,如所在的进程名称,应用的包名,所在的任务栈的taskAffinity等
5、中间再经过一系列调用,又回调到 ActivityThread 的 handleLaunchActivity 来启动 Activity。

借用一张网络图片
11

  • 应用外启动
    通过Launcher 进程启动,Launcher 就是我们桌面程序,当系统开机后, Launcher 也随之被启动。

1、fork并调用ActivityThread的main方法创建app进程
2、然后从 ActivityThread 调用到AMS中的attachApplicationLocked,创建Application
3、Application创建完后,调用ActivityStackSupervisor的attachApplicationLocked方法,最终调用到handleLaunchActivity,进行activity的创建

二、应用内启动源码流程 (startActivity)

我们就从源码出发,一起来看看startActivity后面的流程

2.1 startActivity()

Activity.java

    @Overridepublic void startActivity(Intent intent) {this.startActivity(intent, null);}@Overridepublic void startActivity(Intent intent, @Nullable Bundle options) {if (options != null) {startActivityForResult(intent, -1, options);} else {startActivityForResult(intent, -1);}}public void startActivityForResult(@RequiresPermission Intent intent, int requestCode) {startActivityForResult(intent, requestCode, null);}
    public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,@Nullable Bundle options) {if (mParent == null) {options = transferSpringboardActivityOptions(options);Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);if (ar != null) {//分析启动结果mMainThread.sendActivityResult(mToken, mEmbeddedID, requestCode, ar.getResultCode(),ar.getResultData());}} else {// 最终也是调用 execStartActivity 方法,源码如下if (options != null) {mParent.startActivityFromChild(this, intent, requestCode, options);} else {mParent.startActivityFromChild(this, intent, requestCode);}}}
    public void startActivityFromChild(@NonNull Activity child, @RequiresPermission Intent intent,int requestCode, @Nullable Bundle options) {options = transferSpringboardActivityOptions(options);Instrumentation.ActivityResult ar =mInstrumentation.execStartActivity(this, mMainThread.getApplicationThread(), mToken, child,intent, requestCode, options);if (ar != null) {mMainThread.sendActivityResult(mToken, child.mEmbeddedID, requestCode,ar.getResultCode(), ar.getResultData());}cancelInputsAndStartExitTransition(options);}

上面代码中,最终都会调用了 execStartActivity 方法,该方法会返回一个启动结果。我们一起来看看
frameworks/base/core/java/android/app/Instrumentation.java

/**** @param who              用来启动 Activity 的对象* @param contextThread Binder 对象,具有跨进程通信的能力,传入的是 ApplicationThread* @param token  Binder 对象,指向了服务端一个 ActivityRecord 对象* @param target 当前的 Activity* @param intent  Intent 对象* @param requestCode  请求码*/public ActivityResult execStartActivity(Context who, IBinder contextThread, IBinder token, String target,Intent intent, int requestCode, Bundle options) {IApplicationThread whoThread = (IApplicationThread) contextThread;try {intent.migrateExtraStreamToClipData();intent.prepareToLeaveProcess(who);// 这里的service 就是 ActivityManagerService, 具体可以跟代码看到 // 这么一句 : ServiceManager.getService(Context.ACTIVITY_SERVICE);int result = ActivityManager.getService().startActivity(whoThread, who.getBasePackageName(), intent,intent.resolveTypeIfNeeded(who.getContentResolver()),token, target, requestCode, 0, null, options);checkStartActivityResult(result, intent);} catch (RemoteException e) {}return null;}

通过 Binder 调用 AMS 启动 Activity,我们接着往下看

2.2 startActivityAsUser()

ActivityManagerService.java


public class ActivityManagerService extends IActivityManager.Stub@Overridepublic final int startActivity(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,resultWho, requestCode, startFlags, profilerInfo, bOptions,UserHandle.getCallingUserId());}public final int startActivityAsUser(IApplicationThread caller, String callingPackage,Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,int startFlags, ProfilerInfo profilerInfo, Bundle bOptions, int userId,boolean validateIncomingUser) {enforceNotIsolatedCaller("startActivity");// 首先 检查调用者权限userId = mActivityStartController.checkTargetUser(userId, validateIncomingUser,Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");// TODO: Switch to user app stacks here.return mActivityStartController.obtainStarter(intent, "startActivityAsUser").setCaller(caller).setCallingPackage(callingPackage).setResolvedType(resolvedType).setResultTo(resultTo).setResultWho(resultWho).setRequestCode(requestCode).setStartFlags(startFlags).setProfilerInfo(profilerInfo).setActivityOptions(bOptions).setMayWait(userId).execute();}最后调用的是 ActivityStarter.execute();

上面代码最终调用到了 startActivityAsUser 方法,在内部将所有点的参数都交给了 ActivityStarter

2.3 startActivityUnchecked()

ActivityStarter 该类包含了启动的所有逻辑,比如 Intent 解析以及任务栈等。

ActivityStarter.java

   int execute() {try {if (mRequest.mayWait) {return startActivityMayWait(mRequest.caller, ...);} else {// todo return startActivity(mRequest.caller, ...);  }} finally {onExecutionComplete();}}private int startActivity(IApplicationThread caller, Intent intent, ...) {// 再次检查调用者权限,包括进程检查,intent检查,权限检查等boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, ...);abort |= !mService.mIntentFirewall.checkStartActivity(intent, ...);// 每个 Activity 都会对应一个 ActivityRecord 对象ActivityRecord r = new ActivityRecord(mService, ...);// todo result = startActivityUnchecked(r, sourceRecord ...);}// Note: This method should only be called from {@link startActivity}.private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord ...) {//设置初始化状态setInitialState(r, options, inTask, ...);//判断启动模式,并且在 mLaunchFlags 上追加对应标记computeLaunchingTaskFlags();//设置 Activity 的栈computeSourceStack();//设置 LaunchFlags 到 intent 上mIntent.setFlags(mLaunchFlags);//决定是否用新的栈ActivityRecord reusedActivity = getReusableIntentActivity();...// Should this be considered a new task?int result = START_SUCCESS;if (mStartActivity.resultTo == null && mInTask == null && !mAddingToTask&& (mLaunchFlags & FLAG_ACTIVITY_NEW_TASK) != 0) {newTask = true;// 创建一个新的task来启动result = setTaskFromReuseOrCreateNewTask(taskToAffiliate, topStack);} else// todo mSupervisor.resumeFocusedStackTopActivityLocked();    }

上面代码中会进行一些校验和判断权限,包括进程检查,intent检查,权限检查等

2.4 resumeFocusedStackTopActivityLocked()

ActivityStackSupervisor.java

boolean resumeFocusedStackTopActivityLocked(ActivityStack targetStack...) {return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);return false;}

resumeTopActivityUncheckedLocked -> resumeTopActivityInnerLocked -> startSpecificActivityLocked()
ActivityStack.java

@GuardedBy("mService")boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {if (mStackSupervisor.inResumeTopActivity) {Activity 存在则resumetransaction.setLifecycleStateRequest( ResumeActivityItem.obtain(next.app.repProcState,。。。);mService.getLifecycleManager().scheduleTransaction(transaction);不存在则调用下面这个result = resumeTopActivityInnerLocked(prev, options);} finally {}return result;}@GuardedBy("mService")private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {mStackSupervisor.startSpecificActivityLocked(next, true, false);return true;}

2.5 startSpecificActivityLocked -> realStartActivityLocked()

ActivityStackSupervisor.java
startSpecificActivityLocked -> realStartActivityLocked(); 到这个地方,我们就可以看到真的开始启动 activity,
后面就跟Application 里面一样了

void startSpecificActivityLocked(ActivityRecord r ...) {if (app != null && app.thread != null) {try {// 真的开始启动 activity  ,看下面的方法realStartActivityLocked(r, app, andResume, checkConfig);return;} catch (RemoteException e) {}}}真的开始启动 activityfinal boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,boolean andResume, boolean checkConfig) throws RemoteException {// Create activity launch transaction.final ClientTransaction clientTransaction = ClientTransaction.obtain(app.thread,r.appToken);clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),System.identityHashCode(r), r.info,// TODO: Have this take the merged configuration instead of separate global// and override configs.mergedConfiguration.getGlobalConfiguration(),mergedConfiguration.getOverrideConfiguration(), r.compat,r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,r.persistentState, results, newIntents, mService.isNextTransitionForward(),profilerInfo));// Schedule transaction.mService.getLifecycleManager().scheduleTransaction(clientTransaction);}

ActivityManagerService

ClientLifecycleManager getLifecycleManager() {return mLifecycleManager;}

ClientLifecycleManager

    通过代码,我们可以看到,获取的client就是 ActivityThreadIApplicationThread是一个AIDL文件void scheduleTransaction(ClientTransaction transaction) throws RemoteException {final IApplicationThread client = transaction.getClient();transaction.schedule();}

ClientTransaction

        /** Target client. */private IApplicationThread mClient;public void schedule() throws RemoteException {mClient.scheduleTransaction(this);}

ClientTransactionHandler

//ActivityThread中没有复写scheduleTransaction,会执行到父类的方法//public final class ActivityThread extends ClientTransactionHandler//ClientTransactionHandler.javapublic abstract class ClientTransactionHandler {void scheduleTransaction(ClientTransaction transaction) {transaction.preExecute(this);//发送消息sendMessage(ActivityThread.H.EXECUTE_TRANSACTION, transaction);}}

ActivityThread.java

case EXECUTE_TRANSACTION:final ClientTransaction transaction = (ClientTransaction) msg.obj;mTransactionExecutor.execute(transaction);break;

这里其实就是执行LaunchActivityItem的execute方法,
其赋值的地方在realStartActivityLocked()方法,大家可以回头看看,前面有这么一句代码
clientTransaction.addCallback(LaunchActivityItem.obtain(new Intent(r.intent),

TransactionExecutor.java

public void execute(ClientTransaction transaction) {final IBinder token = transaction.getActivityToken();executeCallbacks(transaction);executeLifecycleState(transaction);mPendingActions.clear();log("End resolving transaction");}/** Cycle through all states requested by callbacks and execute them at proper times. */@VisibleForTestingpublic void executeCallbacks(ClientTransaction transaction) {final List<ClientTransactionItem> callbacks = transaction.getCallbacks();final IBinder token = transaction.getActivityToken();ActivityClientRecord r = mTransactionHandler.getActivityClient(token);final ActivityLifecycleItem finalStateRequest = transaction.getLifecycleStateRequest();final int size = callbacks.size();for (int i = 0; i < size; ++i) {final ClientTransactionItem item = callbacks.get(i);item.execute(mTransactionHandler, token, mPendingActions);item.postExecute(mTransactionHandler, token, mPendingActions);}}

到这里就调用到我们熟悉的handleLaunchActivity了
LaunchActivityItem.java

@Overridepublic void execute(ClientTransactionHandler client, IBinder token,PendingTransactionActions pendingActions) {ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,mPendingResults, mPendingNewIntents, mIsForward,mProfilerInfo, client);client.handleLaunchActivity(r, pendingActions, null /* customIntent */);}

最后调用到ActivityThread

三、 Activity实例化过程

ActivityThread.java

/*** Extended implementation of activity launch. Used when server requests a launch or relaunch.*/@Overridepublic Activity handleLaunchActivity(ActivityClientRecord r,PendingTransactionActions pendingActions, Intent customIntent) {final Activity a = performLaunchActivity(r, customIntent);return a;}Activity实例化过程/**  Core implementation of activity launch. */private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {Activity activity = null;try {// 通过ClassLoader去加载需要启动的activity, 反射实例化Activity对象java.lang.ClassLoader cl = appContext.getClassLoader();activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);} catch (Exception e) {}// 在该方法内部创建window,并设置window回调,activity.attach(appContext, this, getInstrumentation() ...);theme//当实例化Activity对象后,继续执行callActivityOnCreate, 继而调用Activity的onCreate,// 这样就完成了Activity生命周期的第一个回调onCreate方法if (r.isPersistable()) {mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);} else {mInstrumentation.callActivityOnCreate(activity, r.state);}}

下面的代码比较简单,就不贴了
frameworks/base/core/java/android/app/Instrumentation.java


四、 setContentView

这里内容太多,我们另外写一篇文章。

五、 后续生命周期

接下来就是执行 Activity 其他生命周期函数
ActivityThread.java

    @Overridepublic void handleStartActivity(ActivityClientRecord r,PendingTransactionActions pendingActions) {final Activity activity = r.activity;// Restore instance stateif (pendingActions.shouldRestoreInstanceState()) {if (r.isPersistable()) {if (r.state != null || r.persistentState != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state,r.persistentState);}} else if (r.state != null) {mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state);}}// Call postOnCreate()if (pendingActions.shouldCallOnPostCreate()) {activity.mCalled = false;if (r.isPersistable()) {mInstrumentation.callActivityOnPostCreate(activity, r.state,r.persistentState);} else {mInstrumentation.callActivityOnPostCreate(activity, r.state);}}}@Overridepublic void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,String reason) {}

写在最后:
在应用进程创建 activity 后,activity 将执行以下操作:

  1. 初始化值。
  2. 调用构造函数。
  3. 根据 activity 的当前生命周期状态,相应地调用回调方法,如 Activity.onCreate()。
    通常,onCreate() 方法对加载时间的影响最大,因为它执行工作的开销最高:加载和渲染视图,以及初始化运行 activity 所需的对象。

六、 推荐阅读

Java 专栏

SQL 专栏

数据结构与算法

Android学习专栏

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/88472.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Spring MVC】

目录 &#x1f36e;1 什么是 MVC &#xff1f; &#x1f381;2 Spring MVC 的连接 &#x1f358;2.1 RequestMapping 实现 POST 和 GET 请求 &#x1f963;2.2 GetMapping 只支持 GET 请求 &#x1fad6;2.3 PostMapping 只支持 POST 请求 &#x1f36c;3 Spring MVC 获取参数的…

浅析Linux 物理内存外碎片化

本文出现的内核代码来自Linux4.19&#xff0c;如果有兴趣&#xff0c;读者可以配合代码阅读本文。 一、Linux物理内存外碎片化概述 什么是Linux物理内存碎片化&#xff1f;Linux物理内存碎片化包括两种&#xff1a; 1.物理内存内碎片&#xff1a;指分配给用户的内存空间中未…

内网实战1

1、信息收集&#xff1a; 使用nmap做端口扫描&#xff1a; nmap -sV -Pn -T4 192.168.26.174重要端口&#xff1a;80、445、139、135、3306 目录扫描&#xff1a; 访问80端口&#xff1a;发现一个网站是phpstudy搭建的&#xff1b; 发现一个mysql数据库&#xff0c;那我们…

ChatGPT 制作可视化柱形图突出显示第1名与最后1名

对比分析柱形图的用法。在图表中显示最大值与最小值。 像这样的动态图表的展示只需要给ChatGPT,AIGC,OpenAI 发送一个指令就可以了, 人工智能会快速的写出HTML与JS代码来实现。 请使用HTML,JS,Echarts完成一个对比分析柱形图,在图表中突出显示第1名和最后1名用单独一种不…

AVS3变换:PBT、ST和SBT

前面的文章介绍了AVS3中的变换工具IST和ISTS&#xff0c;本文将介绍AVS3中剩余的几种变换工具&#xff1a;基于位置的变换&#xff08;PBT,Position Based Transform&#xff09;、二次变换&#xff08;ST, Secondary Transform&#xff09;和子块变换&#xff08;SBT, Sub-Blo…

万户协同办公平台 ezoffice存在未授权访问漏洞 附POC

文章目录 万户协同办公平台 ezoffice存在未授权访问漏洞 附POC1. 万户协同办公平台 ezoffice简介2.漏洞描述3.影响版本4.fofa查询语句5.漏洞复现6.POC&EXP7.整改意见8.往期回顾 万户协同办公平台 ezoffice存在未授权访问漏洞 附POC 免责声明&#xff1a;请勿利用文章内的相…

Unity 之 Transform.Translate 实现局部坐标系中进行平移操作的方法

文章目录 Translate 默认使用局部坐标也可以转换成世界坐标 Translate 默认使用局部坐标 在Unity中&#xff0c;Transform.Translate是用于在游戏对象的局部坐标系中进行平移操作的方法。这意味着它将游戏对象沿着其自身的轴进行移动&#xff0c;而不是世界坐标轴。这在实现物…

开始MySQL之路——MySQL 事务(详解分析)

MySQL 事务概述 MySQL 事务主要用于处理操作量大&#xff0c;复杂度高的数据。比如说&#xff0c;在人员管理系统中&#xff0c;你删除一个人员&#xff0c;你即需要删除人员的基本资料&#xff0c;也要删除和该人员相关的信息&#xff0c;如信箱&#xff0c;文章等等&#xf…

Unity 结构少继承多组合

为什么不推荐使用继承&#xff1f; 继承是面向对象的四大特性之一&#xff0c;用来表示类之间的 is-a 关系&#xff0c;可以解决代码复用的问题。虽然继承有诸多作用&#xff0c;但继承层次过深、过复杂&#xff0c;也会影响到代码的可维护性。所以&#xff0c;对于是否应该在…

mysql数据备份批处理文件正式版已测试通过

这里写目录标题 1.数据库全表原始数据.ibd文件备份为.sql文件1.1理解date含义 2.备份原始表中部分表 --改进版2.1 backPartTable表内容2.2备份运行2.3实操代码 3.如何将备份的文件进行压缩处理&#xff1f;&#xff1f;执行压缩文件 1.数据库全表原始数据.ibd文件备份为.sql文件…

2023年6月GESP C++ 三级试卷解析

2023年6月GESP C 三级试卷解析 一、单选题&#xff08;每题2分&#xff0c;共30分&#xff09; 1.高级语言编写的程序需要经过以下&#xff08; &#xff09;操作&#xff0c;可以生成在计算机上运行的可执行代码。 A.编辑 B.保存 C.调试 D.编译 【答案】D 【考纲知识点…

动捕设备助力打造沉浸式虚拟现实体验

在纪录片《超时空寻找》中&#xff0c;借助了实时动捕设备&#xff0c;基于三维数字人技术进行老战士与历史场景还原&#xff0c;让抗美援朝老战士可以通过虚拟现实技术&#xff0c;跨越时空与战友实现隔空对话。 随着动捕设备的不断发展&#xff0c;虚拟现实技术越来越成熟&a…