Android性能优化(一)—— 启动优化,冷启动,热启动,温启动
APP启动方式
App启动方式分三种:冷启动(cold start)、热启动(hot start)、温启动(warm start)
▲ 冷启动
系统不存在App进程(APP首次启动或APP被完全杀死)时启动APP此时,APP的启动将经历两个阶段:
第一阶段
1.加载并启动app;2.app启动后,第一时间为app显示一个空白的window;3.创建app进程
第二阶段
系统一旦创建了app进程,app进程就要负责做以下的任务:
1.创建app对象;2.启动主进程ActivityThread;3.创建MainActivity;4.渲染视图;5.执行onLayout;6.执行onDraw7.完成第一次绘制后,把mainActivity替换已经展示的BackgroundWindow,即空白window。
▲ 热启动
当我们按了Home键或其它情况app被切换到后台,再次启动app的过程。热启动时,系统将activity带回前台。如果应用程序的所有activity存在内存中,则应用程序可以避免重复对象初始化、渲染、绘制操作。
如果由于内存不足导致对象被回收,则需要在热启动时重建对象,此时与冷启动时将界面显示到手机屏幕上一样。
▲ 温启动
温启动包含了冷启动的一些操作,由于app进程依然在,温启动只执行冷启动的第二阶段,这代表着它比热启动有更多的开销。
温启动有很多场景,例如:
- 用户按连续按返回退出了app,然后重新启动app;
- 由于系统收回了app的内存,然后重新启动app
App启动优化
app启动优化的方向是冷启动。
空白window问题
app启动时,会短暂的一瞬间白屏,这个动图是我在Application的oncCreate里线程休眠1s实现。虽然如此,但是实际项目中确实存在启动时白屏时间过长的问题。
要看怎么解决,先问▲
为什么会有白屏?
在上面讲冷启动第一阶段,启动app之后,立即展示一个空白的window,那么具体怎么展示,为什么要展示空白的window呢?
我们看app启动流程加载首屏部分源码:
ActivityStack
// Set to false to disable the preview that is shown while a new activity
// is being started.
private static final boolean SHOW_APP_STARTING_PREVIEW = true;
void startActivityLocked(ActivityRecord r, ActivityRecord focusedTopActivity,
boolean newTask, boolean keepCurTransition, ActivityOptions options) {
//…… 省略一万行……
if (!isHomeOrRecentsStack() || numActivities() > 0) {
if (DEBUG_TRANSITION) Slog.v(TAG_TRANSITION,
"Prepare open transition: starting " + r);
//…… 省略一万行……
boolean doShow = true;
if (newTask) {
// Even though this activity is starting fresh, we still need
// to reset it to make sure we apply affinities to move any
// existing activities from other tasks in to it.
// If the caller has requested that the target task be
// reset, then do so.
if ((r.intent.getFlags() & Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) != 0) {
resetTaskIfNeededLocked(r, r);
doShow = topRunningNonDelayedActivityLocked(null) == r;
}
} else if (options != null && options.getAnimationType()
== ActivityOptions.ANIM_SCENE_TRANSITION) {
doShow = false;
}
if (r.mLaunchTaskBehind) {
// Don't do a starting window for mLaunchTaskBehind. More importantly make sure we
// tell WindowManager that r is visible even though it is at the back of the stack.
r.setVisibility(true);
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
// 如果同时满足,则显示空白屏幕
} else if (SHOW_APP_STARTING_PREVIEW && doShow) {
//……
//显示空白屏幕
r.showStartingWindow(prev, newTask, isTaskSwitch(r, focusedTopActivity));
}
} else {
// If this is the first activity, don't do any fancy animations,
// because there is nothing for it to animate on top of.
ActivityOptions.abort(options);
}
}
这里省略了部分代码,只保留关键代码。
显示白屏由两个变量决定:SHOW_APP_STARTING_PREVIEW,在activity启动前时否显示预览;doShow,其默认值为true,但是它由newTask决定,是否为一个全新的activity栈,也就是说,SHOW_APP_STARTING_PREVIEW为true,并且app冷启动,就显示白屏。
那么,能不能不显示白屏呢?
答案是可以的。
两种方法:
- 禁用app启动时window预览的功能
在主题中为首屏activity添加一个注意,禁用window预览的功能,并在manifest中使用
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
<!--禁用预览功能主题-->
<style name="AppSpalshNoPreviewTheme" parent="AppTheme">
<item name="android:windowFullscreen">true</item>
<item name="windowNoTitle">true</item>
<!-- <item name="android:windowContentOverlay">@null</item>-->
<!-- <item name="android:windowBackground">@mipmap/wall</item>-->
<item name="android:windowDisablePreview">true</item>
</style>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.margin.myapplication">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:name=".MyApplication"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".SplashActivity"
android:theme="@style/AppSpalshNoPreviewTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name=".HomeActivity"
android:launchMode="singleTask"/>
</application>
</manifest>
在网上看到说可以将首屏背景设为透明背景,就是我注释掉的两行,但是实际测试发现会透明,但是会出现黑屏的问题,估计这种也不靠谱还麻烦,所以直接忽略它,直接禁用预览功能。
效果如下:
可以看到,我们点了一下app,系统竟然卡住了?!过了1秒多,app才启动起来??什么鬼?其实并不是系统卡住了,而是我们本来应该显示的空白预览屏幕不显示了,所以看起来好像卡住了。嘿嘿嘿,此处突然萌生了一个想法:你手机或者系统有问题,跟我的app代码有啥关系,哈哈哈,你品,你细品,哈哈哈哈……
言归正传,这种方式虽然可以帅锅给系统,并且之前支付宝好像竟然这么干过!但是并不是好的办法,接下来,我们往下看另一种方法。
- 给空白首屏Activity设置一个背景
在style.xml中给SplashActivity添加一个新主题,设置一个背景:
<!--替换首屏的背景的主题-->
<style name="AppSpalshBackgroundTheme" parent="AppTheme">
<item name="android:windowBackground">@mipmap/wall</item>
<item name="android:windowFullscreen">true</item>
<item name="windowNoTitle">true</item>
</style>
效果如下:
看这种效果是不是很好,如果UI再改一下,UI妹子给做一些好看的图,是不是效果更棒了。(另外我发现头条好像也是这样的)
从源头解决
上面两种方式,看似挺不错,尤其是第二种,效果竟然看着还不错??
但是!上面的方式治标不治本只是障眼法,我们还是要从根源上解决问题!
从上面冷启动的介绍可知,app启动过程中,会有如下几个重要过程:
看出点什么了吗?app启动,显示白屏,首屏第一次绘制完成,替换白屏。也就是说,直到首屏显示之前,都是白屏!
所以,要想解决白屏的问题,就要减少白屏显示的时间!也就是说要加快app初始化和首屏绘制的时间。
像上面,我实现长时间白屏,就是在application的onCreate方法中,让线程休眠一段时间
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
看到这段代码,是不是让你产生了一些思路呢?
- 减少Application 初始化的工作量。
我们通常会在Application的onCreate方法中可以做一些轻量化的初始化操作。当onCreate任务越多耗时操作越多,初始化越慢,于是splashActivity启动时间就越晚,白屏时间就越长咯。
一些三方的SDK,文件,设备,线程池,等等工具类,等等尽可能不要在application中初始化。
- 加快UI绘制
其实这个已经是老生常谈的话题了,常常由一下几种方案:
- 减少布局嵌套层级。
布局层级越深,执行measure,layout次数就越多越耗时,ui绘制自然就越慢。我曾经见过一位大神,一个xml嵌套8-9层甚至十几层!我始终想不明白大神到底是计算机专业的还是护理专业的。
此刻我不得不说约束布局——ConstraintLayout是真的香!只要你用的好,布局合理,甚至可以零嵌套!
- 减少布局元素
布局中元素越多,单帧UI绘制就越耗时,所以尽可能减少布局元素。事实上,不管是首屏还是其他的activity或者fragment布局都应该尽可能的减少布局元素。注意有时候可能为了方便,布局中放了一些不可见或占位的控件,应该减少这种情况,因为他们也参与绘制过程的。另外还可以使用viewStub标签,使用时再初始化需要的布局,非常方便。
- 避免过度绘制减少不必要的背景设置。尽可能避免元素重叠。既设置了背景又重叠,就会有不必要的耗时绘制。还是要减少不必要的站位元素。
Android性能优化(一)—— 启动优化,冷启动,热启动,温启动的更多相关文章
- 什么是GPS的冷启动、温启动和热启动?
对于GPS多种启动方式的概念还很模糊,冷启动.热启动.温启动各种专业术语铺天盖地,使得许多用户眼花缭乱. 我们简单从定义上了解一下几种GPS启动的方式,GPS开机启动分为冷启动.温启动.热启动三种. ...
- android 性能优化 -- 启动过程 冷启动 热启动
一.应用的启动方式 通常来说,启动方式分为两种:冷启动和热启动. 1.冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动. 2.热启动:当启 ...
- Android异常与性能优化相关面试问题-冷启动优化面试问题详解
什么是冷启动: 冷启动的定义:冷启动就是在启动应用前,系统中没有该应用的任何进程信息.实际也就是要执行Application.onCreate()方法的那次启动. 冷启动 / 热启动的区别:热启动:用 ...
- Android性能优化(一)之启动加速35%
一.前言 随着项目版本的迭代,App的性能问题会逐渐暴露出来,而好的用户体验与性能表现紧密相关,从本篇文章开始,我将开启一个Android应用性能优化的专题,从理论到实战,从入门到深挖,手把手将性能优 ...
- Android性能优化-App启动优化
原文地址:https://developer.android.com/topic/performance/launch-time.html#common 通常用户期望app响应和加载速度越快越好.一个 ...
- Android性能优化系列之App启动优化
Android性能优化系列之布局优化 Android性能优化系列之内存优化 Android性能优化系列之apk瘦身 应用的启动速度缓慢是我们在开发过程中常常会遇到的问题,比方启动缓慢导致的黑屏.白屏问 ...
- Android 性能优化 ---- 启动优化
Android 性能优化 ---- 启动优化 1.为什么要进行启动优化 一款应用的第一印象很重要,第一印象往往决定了用户的去留.打开一款应用,如果速度很快,很顺畅,那么很容易让人觉得这款应用背后的技术 ...
- Android性能优化之App应用启动分析与优化
前言: 昨晚新版本终于发布了,但是还是记得有测试反馈app启动好长时间也没进入app主页,所以今天准备加个班总结一下App启动那些事! app的启动方式: 1.)冷启动 当启动应用时,后台没 ...
- App 冷启动与热启动及启动白屏优化
介绍一下 app 冷启动和热启动方式来实现 app 秒开的效果.那么,先来看看什么叫冷启动和热启动. 冷启动:指 app 被后台杀死后,在这个状态打开 app,这种启动方式叫做冷启动. 热启动:指 a ...
- 【腾讯Bugly干货分享】Android性能优化典范——第6季
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/580d91208d80e49771f0a07c 导语 这里是Android性能优 ...
随机推荐
- 关于mybatisplus与mybatis的自动填充混用问题
public class MybatisPlusAutoFillHandler implements MetaObjectHandler { //插入时的填充策略 @Override public v ...
- 【Java】Spring注入静态Bean的几种写法
单例模式在Spring注解上的一种拓展用法 写法一,先配置自身Bean,作为静态成员,然后目标Bean作为自身Bean的实例成员' Spring初始化自身Bean时自动装配数据源Bean,从而附属到静 ...
- 【Java】三元运算符 类型提升 问题
代码片段: @Test public void test() { Object o = true ? new Integer(1) : new Double(2); System.out.printl ...
- 【IDEA】创建Maven工程
当前工程,点new - project 选Maven,不需要点选什么骨架创建,骨架创建要下载大量依赖,生成时间太长, 空Maven的目的是让我们自己了解这个项目结构,需要什么依赖再加什么依赖 框线内的 ...
- 【SpringCloud】Re04 Gateway
微服务网关: 1.身份认证 和 权限校验 2.服务路由.负载均衡 3.请求限流 搭建服务网关: 网关是一个独立的服务,同样需要被注册中心注册到,这里依然使用的是Nacos <?xml versi ...
- ubuntu18.04 源码方式安装wine , 警告,libxrender 64-bit development files not found, XRender won't be supported.
警告信息: configure: WARNING: libxrender 64-bit development files not found, XRender won't be supported. ...
- 带有最小间隔时间的队列读取实现 —— 最小等待时间的队列 —— Python编程(续)
接前文: 带有最小间隔时间的队列读取实现 -- 最小等待时间的队列 -- Python编程 由于上次的设计多少有些简单,这里对此丰富一下. ============================== ...
- QT的基础设置(菜单栏、状态栏、任务栏。。。。)
Qt [1] 是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器.下面介绍QT的基础配置 1 ...
- 2021 CCPC 哈尔滨
gym 开场 zsy 签了 J,gjk 签了 B,我读错了 E 的题意,gjk 读对后过了 zsy 读了 K 给我,我记得是模拟赛原题,跟欧拉定理有关,但很难.他俩过了 D I,我大概会了 G 但不会 ...
- 手把手教你ubuntu下移植MJPG-streamer
一.嵌入式视频图像开源库 在嵌入式系统中,常用的视频图像处理开源系统有:luvcview.cheese.motion.mjpg-streamer或者ffmpeg,其中: • luvcview: 基于V ...