Android中的应用启动方式及优化

来源:互联网 发布:精通matlab最优化计算 编辑:程序博客网 时间:2024/05/22 10:44

安卓应用的启动方式分为三种:冷启动、暖启动、热启动。

冷启动

从进程角度上讲,冷启动就是在启动应用前,系统中没有该应用的人和进程信息 (包括 Activity、Service 等) 。所以,冷启动产生的场景就很容易理解了,比如设备开机后应用的第一次启动,系统杀掉应用进程 (如:系统内存吃紧引发的 kill 和 用户主动产生的 kill) 后 的再次启动等。那么自然这种方式下,应用的启动时间最长
应用发生冷启动时,系统有三件任务要做:(1)开始加载并启动应用;(2)应用启动后,显示一个空白的启动窗口;(3)创建应用进程信息;系统创建应用进程后,应用就要做下面这些事情:(1)初始化应用中的对象 (比如 Application 中的工作);(2)启动主线程 (UI 线程) ;(3)创建第一个 Activity;(4)加载内容视图 (Inflating) ;(5)计算视图在屏幕上的位置排版 (Laying out);(6)绘制视图 (draw)。

暖启动

当应用中的 Activities 被销毁,但在内存中常驻时,应用的启动方式就会变为暖启动。相比冷启动,暖启动过程减少了对象初始化、布局加载等工作,启动时间更短。但启动时,系统依然会展示一个空白背景,直到第一个 Activity 的内容呈现为止。

热启动

相比暖启动,热启动时应用做的工作更少,启动时间更短。热启动产生的场景很多,常见如:用户使用返回键退出应用,然后马上又重新启动应用。

启动时间的计算方法
(1)本地时间计算
如果是本地调试的话,统计启动时间还是很简单的,通过命令行方式即可:

adb shell am start -w packagename/activity

输出类似结果:

$ adb shell am start -W com.speed.test/com.speed.test.HomeActivityStarting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.speed.test/.HomeActivity }Status: okActivity: com.speed.test/.HomeActivityThisTime: 496TotalTime: 496WaitTime: 503Complete

(2)网络时间计算
从4.4(API 19)开始,logcat会输出带有Displayed的log。该值代表从app启动进程到完成Activity第一次绘制的时间。该时间内完成了一下流程:

启动进程
初始化对象
创建和初始化Activity
填充布局
第一次绘制app
打出的log如下:

ActivityManager: Displayed com.android.myexample/.StartupTiming: +3s534ms

起始时间点
起始时间点比较容易记录:如果记录冷启动启动时间一般可以在 Application.attachBaseContext() 开始的位置记录起始时间点,因为在这之前 Context 还没有初始化,一般也干不了什么事情,当然这个是要视具体情况来定,其实只要保证在 App 的具体业务逻辑开始执行之前记录起始时间点即可。如果记录热启动启动时间点可以在 Activity.onRestart() 中记录起始时间点。

结束时间点

/***Called when the current {<a href="http://www.jobbole.com/members/57845349">@link</a> Window} of the activity gains or loses* focus.  This is the best indicator of whether this activity is visible* to the user.  The default implementation clears the key tracking* state, so should always be called....*/

通过注释我们可以看到,这个函数是判断 activity 是否可见的最佳位置,所以我们可以在 Activity.onWindowFocusChanged 记录应用启动的结束时间点,不过需要注意的是该函数,在 Activity 焦点发生变化时就会触发,所以要做好判断,去掉不需要的情况。

注:应用的主要启动流程:
(1)用户在 Launcher 程序里点击应用图标时,会通知 ActivityManagerService 启动应用的入口 Activity
(2) ActivityManagerService 发现这个应用还未启动,则会通知 Zygote 进程孵化出应用进程,然后在这个应用进程里执行 ActivityThread 的 main 方法。
(3)应用进程接下来通知 ActivityManagerService 应用进程已启动
(4)然后 ActivityManagerService 通知应用进程创建入口 Activity 的实例,并执行它的生命周期函数。

冷启动优化方案:
1、google给出的方案
相关链接:https://material.io/guidelines/patterns/launch-screens.html#
(1)新建一个名为 shape_launch.xml 的 drawable 文件,内容如下:

<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android"    android:opacity="opaque">    <item android:drawable="@color/colorPrimary"/>    <item >        <bitmap            android:src="@mipmap/ic_launcher"            android:gravity="center" />    </item></layer-list>

修改主体样式

<style name="LaunchStyle" parent="AppTheme">    <item name="android:windowBackground">@drawable/shape_launch</item></style>

这个主题样式设置给第一个启动的 Activity ,如:

<activity     android:name=".MainActivity"    android:theme="@style/LaunchStyle">    <intent-filter>        <action android:name="android.intent.action.MAIN" />        <category android:name="android.intent.category.LAUNCHER" />    </intent-filter></activity>

再修改该 Activity 类的代码,在加载布局视图前,将主题修改回来:

@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setTheme(R.style.AppTheme);    setContentView(R.layout.activity_main);}

2、使用与主界面 UI 框架一致的 placeholder 内容,这种情况下需要计算诸如 Statusbar、Toolbar 控件的高度,shape_launch.xml 内容如下:

<?xml version="1.0" encoding="utf-8"?><layer-list xmlns:android="http://schemas.android.com/apk/res/android"    android:opacity="opaque">    <item android:drawable="@color/colorPrimaryDark"/>    <item        android:drawable="@color/colorPrimary"        android:top="25dp"/>    <item        android:top="81dp"        android:drawable="@android:color/white">    </item></layer-list>

相关文章:http://android.jobbole.com/84174/
http://yifeng.studio/2016/11/15/android-optimize-for-cold-start/

0 0