Android Application启动流程分析

本文深入解析了Android应用的启动流程,从用户点击图标开始,涉及App基础理论,包括Android应用的独立进程、组件概念,再到启动流程,包括创建进程、绑定Application和启动Activity的详细步骤。文章介绍了Zygote进程的角色,以及ActivityManagerService如何协调各个组件。通过对启动流程的分析,帮助读者理解Android应用启动背后的技术原理。
摘要由CSDN通过智能技术生成

译者注:
原文分成两个部分, 链接如下:
http://multi-core-dump.blogspot.com/2010/04/android-application-launch.html
http://multi-core-dump.blogspot.com/2010/04/android-application-launch-part-2.html
本文合二为一, 章节标题由译者加注.

作者曾经在高通的Android性能组工作, 主要工作是优化Android Application的启动时间.

1, App基础理论

要想优化App启动时间, 第一步就是了解App启动进程的工作原理. 有几个基础理论:

Android Application与其他移动平台有两个重大不同点:

  1. 每个Android App都在一个独立空间里, 意味着其运行在一个单独的进程中, 拥有自己的VM, 被系统分配一个唯一的user ID.
  2. Android App由很多不同组件组成, 这些组件还可以启动其他App的组件. 因此, Android App并没有一个类似程序入口的main()方法.

Android Application组件包括:

  • Activities: 前台界面, 直接面向User, 提供UI和操作.
  • Services: 后台任务.
  • Broadcast Receivers: 广播接收者.
  • Contexnt Providers: 数据提供者.

Android进程与Linux进程一样. 默认情况下, 每个apk运行在自己的Linux进程中. 另外, 默认一个进程里面只有一个线程---主线程. 这个主线程中有一个Looper实例, 通过调用Looper.loop()从Message队列里面取出Message来做相应的处理.

那么, 这个进程何时启动的呢?
简单的说, 进程在其需要的时候被启动. 任意时候, 当用户或者其他组件调取你的apk中的任意组件时, 如果你的apk没有运行, 系统会为其创建一个新的进程并启动. 通常, 这个进程会持续运行直到被系统杀死. 关键是: 进程是在被需要的时候才创建的.

举个例子, 如果你点击email中的超链接, 会在浏览器里面打开一个网页. Email App和浏览器App是两个不同的App, 运行在不同的进程中. 这次点击事件促使Android系统去创建了一个新的进程来实例化浏览器的组件.

首先, 让我们快速看下Android启动流程. 与众多基于Linux内核的系统类似, 启动系统时, bootloader启动内核和init进程. init进程分裂出更多名为"daemons(守护进程)"的底层的Linux进程, 诸如android debug deamon, USB deamon等. 这些守护进程处理底层硬件相关的接口.

随后, init进程会启动一个非常有意思的进程---"Zygote". 顾名思义, 这是一个Android平台的非常基础的进程. 这个进程初始化了第一个VM, 并且预加载了framework和众多App所需要的通用资源. 然后它开启一个Socket接口来监听请求, 根据请求孵化出新的VM来管理新的App进程. 一旦收到新的请求, Zygote会基于自身预先加载的VM来孵化出一个新的VM创建一个新的进程.

启动Zygote之后, init进程会启动runtime进程. Zygote会孵化出一个超级管理进程---System Server. SystemServer会启动所有系统核心服务, 例如Activity Manager Service, 硬件相关的Service等. 到此, 系统准备好启动它的第一个App进程---Home进程了.

2, 启动App流程

用户点击Home上的一个App图标, 启动一个应用时:


app launch

Click事件会调用startActivity(Intent), 会通过Binder IPC机制, 最终调用到ActivityManagerService. 该Service会执行如下操作:

  • 第一步通过PackageManager的resolveIntent()收集这个intent对象的指向信息.
  • 指向信息被存储在一个intent对象中.
  • 下面重要的一步是通过grantUriPermissionLocked()方法来验证用户是否有足够的权限去调用该intent对象指向的Activity.
  • 如果有权限, ActivityManagerService会检查并在新的task中启动目标activity.
  • 现在, 是时候检查这个进程的ProcessRecord是否存在了.

如果ProcessRecord是null, ActivityManagerService会创建新的进程来实例化目标activity.

以桌面启动一个应用Activity为例,onClick事件后,会调用startActivityForResult(Intent, int)

public void startActivityForResult(Intent intent, int requestCode) {
if (mParent == null) {
//Activity启动执行交由Instrumentation对象去处理
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode);
//mMainThread 在attach方法中被设置,当ActivityThread PerformLauchActivity,调用attach把ActivityThread.this传送过来
//mMainThread.getApplicationThread()它是一个进程通信服务端存根对象,提供了很多操作ActivityThread的方法,它继承了ApplicationThreadNative 
if (ar != null) {
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
if (requestCode >= 0) {
// If this start is requesting a result, we can avoid making
// the activity visible until the result is received. Setting
// this code during onCreate(Bundle savedInstanceState) or onRes

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值