安卓App启动——Application的启动流程,从startActivity讲起

public class ActivityManagerService extends IActivityManager.Stub    implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback, ActivityManagerGlobalLock{
        public int startActivity(IApplicationThread caller, String callingPackage,
              Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
              int startFlags, ProfilerInfo profilerInfo, Bundle bOptions) {
          return mActivityTaskManager.startActivity(caller, callingPackage, null, intent,
                  resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions);
      }
}

我们可以看到调用了 mActivityTaskManager.startActivity,参数中IApplicationThread 我们留到后面讲。我们先往下追踪

ActivityTaskManagerService.java{

return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                  resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions,
                  UserHandle.getCallingUserId());

}

UserHandle.getCallingUserId()是获取当前的调用userId我们留到后面讲,当前我们继续追踪。

public int startActivityAsUser(IApplicationThread caller, String callingPackage,
              String callingFeatureId, Intent intent, String resolvedType, IBinder resultTo,
              String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo,
              Bundle bOptions, int userId) {
          return startActivityAsUser(caller, callingPackage, callingFeatureId, intent, resolvedType,
                  resultTo, resultWho, requestCode, startFlags, profilerInfo, bOptions, userId,
                  true /*validateIncomingUser*/);//最后一个参数设置了固定值true
      }
private int startActivityAsUser(IApplicationThread caller, String callingPackage,
1179              @Nullable String callingFeatureId, Intent intent, String resolvedType,
1180              IBinder resultTo, String resultWho, int requestCode, int startFlags,
1181              ProfilerInfo profilerInfo, Bundle bOptions, int userId, boolean validateIncomingUser) {
1182          assertPackageMatchesCallingUid(callingPackage);//判断当前调用packagename和调 
                                                             //用uid是否匹配。留后面讲,这 
                                                             //里不细究
1183          enforceNotIsolatedCaller("startActivityAsUser");//判断当前调用userid是否在合 
                                                              //理沙箱合理范围内
1184          //验证用户userid/callingpid/callinguid
1185          userId = getActivityStartController().checkTargetUser(userId, validateIncomingUser,
1186                  Binder.getCallingPid(), Binder.getCallingUid(), "startActivityAsUser");
1187  
1188          // 利用ActivityStarter工厂模式创建ActivityStarter
1189          return getActivityStartController().obtainStarter(intent, "startActivityAsUser")
1190                  .setCaller(caller)
1191                  .setCallingPackage(callingPackage)
1192                  .setCallingFeatureId(callingFeatureId)
1193                  .setResolvedType(resolvedType)
1194                  .setResultTo(resultTo)
1195                  .setResultWho(resultWho)
1196                  .setRequestCode(requestCode)
1197                  .setStartFlags(startFlags)
1198                  .setProfilerInfo(profilerInfo)
1199                  .setActivityOptions(bOptions)
1200                  .setUserId(userId)
1201                  .execute();//执行execute
1202  
1203      }

我们看看execute都执行了什么

int execute() {
        try {
            if (mRequest.intent != null && mRequest.intent.hasFileDescriptors()) {
                throw new IllegalArgumentException("File descriptors passed in Intent");
            }
            final LaunchingState launchingState;
            synchronized (mService.mGlobalLock) {
                final ActivityRecord caller = ActivityRecord.forTokenLocked(mRequest.resultTo);
                final int callingUid = mRequest.realCallingUid == Request.DEFAULT_REAL_CALLING_UID
                        ?  Binder.getCallingUid() : mRequest.realCallingUid;
                launchingState = mSupervisor.getActivityMetricsLogger().notifyActivityLaunching(
                        mRequest.intent, caller, callingUid);
            }
            if (mRequest.activityInfo == null) {
                mRequest.resolveActivity(mSupervisor);
            }
            if (mRequest.intent != null) {
                String intentAction = mRequest.intent.getAction();
                String callingPackage = mRequest.callingPackage;
                if (intentAction != null && callingPackage != null
                        && (Intent.ACTION_REQUEST_SHUTDOWN.equals(intentAction)
                                || Intent.ACTION_SHUTDOWN.equals(intentAction)
                                || Intent.ACTION_REBOOT.equals(intentAction))) {
                    ShutdownCheckPoints.recordCheckPoint(intentAction, callingPackage, null);
                }
            }

            int res;
            synchronized (mService.mGlobalLock) {
                final boolean globalConfigWillChange = mRequest.globalConfig != null
                        && mService.getGlobalConfiguration().diff(mRequest.globalConfig) != 0;
                final Task rootTask = mRootWindowContainer.getTopDisplayFocusedRootTask();
                if (rootTask != null) {
                    rootTask.mConfigWillChange = globalConfigWillChange;
                }
                ProtoLog.v(WM_DEBUG_CONFIGURATION, "Starting activity when config "
                        + "will change = %b", globalConfigWillChange);

                final long origId = Binder.clearCallingIdentity();

                res = resolveToHeavyWeightSwitcherIfNeeded();
                if (res != START_SUCCESS) {
                    return res;
                }
                res = executeRequest(mRequest);

                Binder.restoreCallingIdentity(origId);

                if (globalConfigWillChange) {
                    mService.mAmInternal.enforceCallingPermission(
                            android.Manifest.permission.CHANGE_CONFIGURATION,
                            "updateConfiguration()");
                    if (rootTask != null) {
                        rootTask.mConfigWillChange = false;
                    }
                    ProtoLog.v(WM_DEBUG_CONFIGURATION,
                                "Updating to new configuration after starting activity.");

                    mService.updateConfigurationLocked(mRequest.globalConfig, null, false);
                }
                final ActivityOptions originalOptions = mRequest.activityOptions != null
                        ? mRequest.activityOptions.getOriginalOptions() : null;
                final boolean newActivityCreated = mStartActivity == mLastStartActivityRecord;
                mSupervisor.getActivityMetricsLogger().notifyActivityLaunched(launchingState, res,
                        newActivityCreated, mLastStartActivityRecord, originalOptions);
                if (mRequest.waitResult != null) {
                    mRequest.waitResult.result = res;
                    res = waitResultIfNeeded(mRequest.waitResult, mLastStartActivityRecord,
                            launchingState);
                }
                return getExternalResult(res);
            }
        } finally {
            onExecutionComplete();
        }
    }

1、

### Android 应用程序启动流程 Android 应用的启动是一个复杂的过程,涉及多个组件之间的交互。以下是应用启动的主要阶段及其描述: #### 1. **Launcher 发起 Intent** 当用户点击应用程序图标时,Launcher 将发送一个 `Intent` 给系统的 ActivityManagerService (AMS),该 `Intent` 包含目标活动(Activity)的信息[^1]。 #### 2. **Zygote 创建进程** AMS 接收到请求后会检查目标应用是否已经运行在一个现有的进程中。如果未找到,则 AMS 请求 Zygot 进程创建一个新的虚拟机实例并加载必要的库文件。 #### 3. **Application 对象初始化** 新进程被创建之后,系统调用 Application 类的构造函数以及其子类中的 `onCreate()` 方法完成全局上下文环境设置工作[^3]。 #### 4. **Activity 加载与显示** 随后进入主线程执行栈中第一个待处理的任务——即我们定义的第一个 activity 的生命周期方法链:从 attach 到 window decor view inflation 再到最终绘制界面给用户看整个过程都需要耗费一定时间资源去完成操作。 ### 常见启动问题及解决方案 #### 性能优化建议 为了提高用户体验,在实际开发过程中需要注意以下几个方面可能影响到冷热启速度的因素,并采取相应措施加以改进: - **减少不必要的依赖注入框架** 如果项目里引入了很多第三方库来做DI(比如 Dagger,Hilt),那么这些工具本身也会增加额外开销,尤其是在第一次打开的时候因为它们需要解析配置文件等等动作都会延长耗时. - **延迟非必要逻辑至后台线程或者后续时机再做** 把一些不紧急但又必须做的事情安排在稍后的时刻去做而不是放在app刚起来就马上干掉它这样可以有效降低首屏渲染所需的时间成本从而让页面更快呈现出来供访问者查看内容. - 使用 TraceView 工具定位瓶颈所在位置以便针对性修复性能缺陷等问题 ```java @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); // Example of delaying non-critical tasks to background thread. new Thread(() -> { heavyTask(); }).start(); setContentView(R.layout.activity_main); } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闽农qq:994955138

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值