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). 简化页面布局嵌套。

相关推荐
CheungChunChiu34 分钟前
Android10 rk3399 以太网接入流程分析
android·framework·以太网·eth·net·netd
木头没有瓜1 小时前
ruoyi 请求参数类型不匹配,参数[giftId]要求类型为:‘java.lang.Long‘,但输入值为:‘orderGiftUnionList
android·java·okhttp
键盘侠0071 小时前
springboot 上传图片 转存成webp
android·spring boot·okhttp
江上清风山间明月2 小时前
flutter bottomSheet 控件详解
android·flutter·底部导航·bottomsheet
Crossoads3 小时前
【汇编语言】外中断(一)—— 外中断的魔法:PC机键盘如何触发计算机响应
android·开发语言·数据库·深度学习·机器学习·计算机外设·汇编语言
sunphp开发者4 小时前
黑客攻击网站,篡改首页问题排查修复
android·js
我又来搬代码了5 小时前
【Android Studio】创建新项目遇到的一些问题
android·ide·android studio
ggs_and_ddu9 小时前
Android--java实现手机亮度控制
android·java·智能手机
zhangphil14 小时前
Android绘图Path基于LinearGradient线性动画渐变,Kotlin(2)
android·kotlin
watl015 小时前
【Android】unzip aar删除冲突classes再zip
android·linux·运维