Android启动速度优化

本节主要内容:了解APP启动流程、启动状态、查看启动时间、CPU Profile定位启动耗时代码、StrictMode严苛模式检测不合理写法、解决启动黑白屏问题。

一、APP启动流程

①用户点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;

②system_server进程接收到请求后,向zygote进程发送创建进程的请求;

③Zygote进程fork出新的子进程,即App进程;

④App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;

⑤system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;

⑥App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;

⑦主线程在收到Message后,通过反射机制创建目标Activity,并回调Activity.onCreate()等方法。

⑧至此,App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面。

二、APP的三种启动状态

冷启动、温启动与热启动,三种启动状态,每种状态都会影响应用向用户显示所需的时间。

1、冷启动

冷启动是指应用从头开始启动:系统进程在冷启动后才创建应用进程。发生冷启动的情况包括应用

自设备启动后或系统终止应用后首次启动。

2、热启动

在热启动中,系统的所有工作就是将 Activity 带到前台。只要应用的所有 Activity 仍驻留在内存

中,应用就不必重复执行对象初始化、布局加载和绘制。

3、温启动

温启动包含了在冷启动期间发生的部分操作;同时,它的开销要比热启动高。有许多潜在状态可视

为温启动。例如:

用户在退出应用后又重新启动应用。进程可能未被销毁,继续运行,但应用需要执行onCreate() 从头开始重新创建 Activity。

系统将应用从内存中释放,然后用户又重新启动它。进程和 Activity 需要重启,但传递到onCreate() 的已保存的实例 state bundle 对于完成此任务有一定助益。

4、在您的应用出现以下情况时将其启动时间视为过长:

冷启动用了 5 秒或更长时间。

温启动用了 2 秒或更长时间。

热启动用了 1.5 秒或更长时间。

三、查看启动时间

1、系统日志统计

在 Android 4.4(API 级别 19)及更高版本中,logcat 包含一个输出行,其中包含名为 Displayed 的值。此值代表从启动进程到在屏幕上完成对应 Activity 的绘制所用的时间。

java 复制代码
ActivityManager: Displayed com.android.myexample/.StartupTiming: 274ms

如果我们使用异步懒加载的方式来提升程序画面的显示速度,这通常会导致的一个问题是,程序画面已经显示,同时 Displayed 日志已经打印,可是内容却还在加载中。为了衡量这些异步加载资源所耗费的时间,我们可以在异步加载完毕之后调用 activity.reportFullyDrawn() 方法来让系统打印到调用此方法为止的启动耗时。

2、adb 命令统计

java 复制代码
adb shell am start -S -W com.file.util/.WwwActivity

WaitTime:总的耗时,包括前一个应用Activity pause的时间和新应用启动的时间;

TotalTime表示新应用启动的耗时,包括新进程的启动和Activity的启动,但不包括前一个应用Activity pause的耗时。我们一般只要关心TotalTime即可,这个时间才是自己应用真正启动的耗时。

四、CPU Profile

1、CPU Profile工具

使用CPU Profile工具定位到启动耗时相关代码,进行分析和解决耗时问题。 具体操作:

1)点击app,选择Edit Configuration...

  1. 设置好页面的配置后,点击Apply --》 OK

3)点击Profiler运行APP

4)点击Stop,等待一段时间,生成

5)Call Chart 表绿色部分代表我们写的代码的运行时间,可以看到方法执行所用到的时间等信息,根据耗时比较多的去查看源代码,是否在主线程做了耗时操作,进而优化代码。

2、Debug API

除了直接使用 Profile 启动之外,我们还可以借助Debug API生成trace文件:

java 复制代码
public class MyApplication extends Application {
	public MyApplication() {
		Debug.startMethodTracing("test");
	}
}
java 复制代码
public class MainActivity extends AppCompatActivity {
	@Override
	public void onWindowFocusChanged(boolean hasFocus) {
		super.onWindowFocusChanged(hasFocus);
		Debug.stopMethodTracing();
	}
}

运行App,则会在sdcard中生成一个test.trace文件(需要sdcard读写权限)。将手机中的trace文件保存至电脑,随后拖入Android Studio即可。

五、StrictMode严苛模式

StrictMode是一个开发人员工具,它可以检测出我们可能无意中做的事情,并将它们提请我们注意,以便我们能够修复它们。

StrictMode最常用于捕获应用程序主线程上的意外磁盘或网络访问。帮助我们让磁盘和网络操作远离主线程,可以使应用程序更加平滑、响应更快。

java 复制代码
public class MyApplication extends Application {
	@Override
	public void onCreate() {
		if (BuildConfig.DEBUG) {
			//线程检测策略
			StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
				.detectDiskReads() //读、写操作
				.detectDiskWrites()
				.detectNetwork() // or .detectAll() for all detectable problems
				.penaltyLog()
                .penaltyDeath()
				.build());

			StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
				.detectLeakedSqlLiteObjects() //Sqlite对象泄露
				.detectLeakedClosableObjects() //未关闭的Closable对象泄露
				.penaltyLog() //违规打印日志
				.penaltyDeath() //违规崩溃
				.build());
		}
	}
}

六、启动黑白屏

当系统加载并启动 App 时,需要耗费相应的时间,这样会造成用户会感觉到当点击 App 图标时会有 "延迟" 现象,为了解决这一问题,Google 的做法是在 App 创建的过程中,先展示一个空白页面,让用户体会到点击图标之后立马就有响应。

如果你的application或activity启动的过程太慢,导致系统的BackgroundWindow没有及时被替换,就会出现启动时白屏或黑屏的情况(取决于Theme主题是Dark还是Light)。

消除启动时的黑/白屏问题,大部分App都采用自己在Theme中设置背景图的方式来解决。

XML 复制代码
<style name="AppTheme.Launcher">
	<item name="android:windowBackground">@drawable/bg</item>
</style>
XML 复制代码
<activity
	android:name=".WwwActivity"
	android:screenOrientation="portrait"
	android:theme="@style/AppTheme.Launcher">
	<intent-filter>
		<action android:name="android.intent.action.MAIN" />
		<category android:name="android.intent.category.LAUNCHER" />
	</intent-filter>
</activity>

然后在Activity的onCreate方法,把Activity设置回原来的主题。

java 复制代码
@Override
protected void onCreate(Bundle savedInstanceState) {
	//替换为原来的主题,在onCreate之前调用
	setTheme(R.style.AppTheme);
	super.onCreate(savedInstanceState);
}

这么做,只是提高启动的用户体验。并不能做到真正的加快启动速度。

总结:

1). APPlication初始化三方SDK时,合理的使用异步初始化、延迟初始化、懒加载机制。

2). 启动过程避免耗时操作,如数据库 I/O操作不要放在主线程执行。

3). 类加载优化:提前异步执行类加载。

4). 合理使用IdleHandler进行延迟初始化。

5). 简化页面布局嵌套。

相关推荐
REDcker1 小时前
Android WebView 版本升级方案详解
android·音视频·实时音视频·webview·js·编解码
麦兜*1 小时前
【springboot】图文详解Spring Boot自动配置原理:为什么@SpringBootApplication是核心?
android·java·spring boot·spring·spring cloud·tomcat
le1616161 小时前
Android 依赖种类及区别:远程仓库依赖、打包依赖、模块依赖、本地仓库依赖
android
lxysbly1 小时前
psp模拟器安卓版带金手指
android
云上凯歌2 小时前
02 Spring Boot企业级配置详解
android·spring boot·后端
hqiangtai2 小时前
Android 高级专家技术能力图谱
android·职场和发展
aqi002 小时前
FFmpeg开发笔记(九十七)国产的开源视频剪辑工具AndroidVideoEditor
android·ffmpeg·音视频·直播·流媒体
stevenzqzq2 小时前
Android Koin 注入入门教程
android·kotlin
炼金术3 小时前
SkyPlayer v1.1.0 - 在线视频播放功能更新
android·ffmpeg
用户276038157813 小时前
鲲鹏+昇腾:开启 AI for Science 新范式——基于PINN的流体仿真加速实践
android