原文:https://www.jianshu.com/p/a5532ecc8377

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

  1. APP基础理论

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

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

    1. 每个Android App都在一个独立空间里,意味着其运行在一个单独的进程中,拥有自己的VM,

      被系统分配一个唯一的user ID

    2. Android APP由很多不同的组件组成,这些组件还可以启动其他APP的组件,因此,android APP

      并没有一个类似程序入口的main()方法

    Android application组件包括:

    Activity:前台界面,直接面向User,提供UI和操作

    Service:后台任务

    Broadcast Receivers:广播接受者

    Context 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进程了.

  1. 启动APP流程

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

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

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

    2.1创建进程

    ActivityManagerService调用startProcessLocked()方法来创建新的进程, 该方法会通过前面讲到的socket通道传递参数给Zygote进程. Zygote孵化自身,

    并调用ZygoteInit.main()方法来实例化ActivityThread对象并最终返回新进程的pid.

    ActivityThread随后依次调用Looper.prepareLoop()和Looper.loop()来开启消息循环.

    流程图如下:

    1. 绑定Application

      接下来要做的就是将进程和指定的Application绑定起来. 这个是通过上节的ActivityThread对象中调用bindApplication()方法完成的.

      该方法发送一个BIND_APPLICATION的消息到消息队列中, 最终通过handleBindApplication()方法处理该消息. 然后调用makeApplication()方法

      来加载App的classes到内存中.

      流程图如下:

    2. 启动activity

      经过前两个步骤之后, 系统已经拥有了该application的进程. 后面的调用顺序就是普通的从一个已经存在的进程中启动一个新进程的activity了.

      实际调用方法是realStartActivity(), 它会调用application线程对象中的sheduleLaunchActivity()发送一个LAUNCH_ACTIVITY消息到

      消息队列中, 通过 handleLaunchActivity()来处理该消息.

      假设点击的是一个视频浏览的App, 其流程如下:

Android 启动流程分析的更多相关文章

  1. Cocos2d-x3.3RC0的Android编译Activity启动流程分析

    本文将从引擎源代码Jni分析Cocos2d-x3.3RC0的Android Activity的启动流程,以下是具体分析. 1.引擎源代码Jni.部分Java层和C++层代码分析 watermark/2 ...

  2. 【转】android SystemUI 流程分析

    android4 SystemUI 流程分析 什么是SystemUI? 对于Phone来说SystemUI指的是:StatusBar(状态栏).NavigationBar(导航栏).而对于Tablet ...

  3. Android5 Zygote 与 SystemServer 启动流程分析

    Android5 Zygote 与 SystemServer 启动流程分析 Android5 Zygote 与 SystemServer 启动流程分析 前言 zygote 进程 解析 zygoterc ...

  4. u-boot启动流程分析(2)_板级(board)部分

    转自:http://www.wowotech.net/u-boot/boot_flow_2.html 目录: 1. 前言 2. Generic Board 3. _main 4. global dat ...

  5. u-boot启动流程分析(1)_平台相关部分

    转自:http://www.wowotech.net/u-boot/boot_flow_1.html 1. 前言 本文将结合u-boot的“board—>machine—>arch—> ...

  6. Netty 拆包粘包和服务启动流程分析

    Netty 拆包粘包和服务启动流程分析 通过本章学习,笔者希望你能掌握EventLoopGroup的工作流程,ServerBootstrap的启动流程,ChannelPipeline是如何操作管理Ch ...

  7. Uboot启动流程分析(转载)

    最近一段时间一直在做uboot移植相关的工作,需要将uboot-2016-7移植到单位设计的ARMv7的处理器上.正好元旦放假三天闲来无事,有段完整的时间来整理下最近的工作成果.之前在学习uboot时 ...

  8. Storm集群启动流程分析

    Storm集群启动流程分析 程序员 1.客户端运行storm nimbus时,会调用storm的python脚本,该脚本中为每个命令编写了一个方法,每个方法都可以生成一条相应的Java命令. 命令格式 ...

  9. 【转】Netty 拆包粘包和服务启动流程分析

    原文:https://www.cnblogs.com/itdragon/archive/2018/01/29/8365694.html Netty 拆包粘包和服务启动流程分析 通过本章学习,笔者希望你 ...

随机推荐

  1. 设置Android模拟器的窗口大小

    Android SDK 中两个位置可以设置Android模拟器的窗口大小 1.设置Android模拟器的分辨率 Android Virtual Device Manager中创建AVD时,窗口中部Re ...

  2. jQuery和ajax【“Asynchronous Javascript And XML】

    环境搭建 搭建一个jQuery的开发环境非常方便,可以通过下列几个步骤进行. 下载jQuery文件库 在jQuery的官方网站(http://jquery.com)中,下载最新版本的jQuery文件库 ...

  3. 生成对抗网络GAN详解与代码

    1.GAN的基本原理其实非常简单,这里以生成图片为例进行说明.假设我们有两个网络,G(Generator)和D(Discriminator).正如它的名字所暗示的那样,它们的功能分别是: G是一个生成 ...

  4. C#学习笔记06--类/对象/访问修饰符/方法

    编程思想   1.面向过程   面向过程是要把问题解决的过程分成有一定顺序的不同步骤, 然后按照步骤一步步的将问题解决.   2.面向对象   面向对象解决问题的思路是先分析问题中所涉及的对象, 然后 ...

  5. sqlserver交换数据行中的指定列

    <!-- 次序上移下移 --> <update id="upOrDown" parameterType="java.util.Map"> ...

  6. mysql只会使用到一个索引的原因

    select count(1) from table1 where column1 = 1 and column2 = 'foo' and column3 = 'bar' 其中column1,colu ...

  7. 剑指offer52:正则表达式匹配

    1 题目描述 请实现一个函数用来匹配包括'.'和'*'的正则表达式.模式中的字符‘.’表示任意一个字符,而'*'表示它前面的字符可以出现任意次(包含0次). 在本题中,匹配是指字符串的所有字符匹配整个 ...

  8. Scratch运动模块——有趣的弹球游戏(一)

    大家好!我是蓝老师,有了前几期Scratch的基础,相信大家早已摩拳擦掌,跃跃欲试了,甚至还有些小伙伴已经编写了非常不错的程序. 学习编程就是这样不断探索.主动思考.解决问题的过程. 本期内容: 课程 ...

  9. Scratch—点亮生日蜡烛

    过生日是小朋友们创作Scratch作品经常会用到的素材,今天介绍使用一些基础技能来点亮生日蜡烛的实现方法. 1.角色设计只有三种:生日蛋糕.未点燃的蜡烛.已点燃的蜡烛. 2.未点燃的蜡烛:在程序启动时 ...

  10. SAS学习笔记5 字符截取语句(index、compress、substr、scan函数)

    index:返回一个字符串中,某个特定字符或字符串的位置,找不到时返回0 compress:从一个字符串移除特定的字符 substr函数 字符替换与提取字符 substr(s, p, n)从变量s的第 ...