一. 前言
当用户在手机桌面上点击一个从未打开过的App时(也就是冷启动),到进入第一个页面显示这段时间,默认情况下您的App会首先出现一个白色/黑色屏,过一段时间才是进入第一个Activity显示其具体布局内容。
对于一个专业的App来说,这种用户体验肯定是不能接受的,不仅会收到用户吐槽,还会造成公司品牌受损。因此提升App的启动速度是增强用户体验的重要指标。
而这个问题,相信很多朋友很早之前就遇到了,而且在网上也能搜到一大堆关于此问题的文章。但是,我看了前几页几乎所有的文章之后,让人失望的是这些文章要么是只提供解决方案,也就是说怎么弄之后问题就解决了,至于为什么,不知道,反正大家都这么干;极少数有分析原因的文章,又让人无法信服,让人怀疑甚至分析是错误的。
为了得到一个让我自己信服的答案,哥不惜拖着疲惫的身躯深夜撸码,一探究竟,接下来就给大家揭晓一下真实情况到底是什么样的。
二. 冷启动白屏的真正原因
首先,要明确一点的是,要想弄清楚冷启动白屏的真正原因,就必须知道冷启动Android经历了哪些代码流程。
我们都知道Launcher本身也是一个特殊的App,其界面就是列出所有的App Icon,当用户在手机桌面上点击一个从未打开过的App时,其实是和正常的startActivity是一样的。
通过阅读源码(具体代码细节太长,这里就省略了),我们知道主分支会经历如下过程:
1Launcher startActivity
2-> AMS查找应用进程是否创建
3-> 未创建,AMS通知从Zygote进程中fork创建出一个新的进程分配给该应用
4-> 进程创建完毕,AMS通过Binder通知应用进程
5-> ActivityThread 调用 performLaunchActivity
6-> Application构造函数及attachBaseContext(),onCreate()
7-> new Activity(), 并为此Activity创建一个new PhoneWindow(this)
8-> Activity onCreate()
9-> Activity setContentView()
10-> new DecorView() & addView(contentRoot, contentParent)
11-> onFinishInflate(): 此步骤只是inflate 所有的DecorView上的布局views,并不可见
12-> Activity onStart()
13-> Activity onResume()
14-> window.addView(mDecorView)
15-> View onAttachedToWindow() onMeasure() onSizeChanged() onLayout() onDraw()
16-> 至此步为止才把DecorView加给Window,应用首页才可见,onWindowFocusChanged(true)
17-> Activity onPause()
18-> View onWindowFocusChanged(false )
19-> Activity onStop()
20-> Activity onDestroy()
21-> View onDetackedFromWindow()
从以上流程,我们至少可以知道如下几个重要的信息:
1)Application onCreate()与Activity,Window的生成时间,以及Activity和View生命周期的严格执行顺序。
2)为什么只有当Activity在执行onResume()生命周期之后用户才能真正看到布局内容。
3)Activity, Window,DecorView及其之上的contentRoot, parentRoot, ToolBar之间的关系。
图片来源于网络
那么问题来了:按道理来讲,在点击了App Icon之后一直到onResume才能看到App的第一屏页面才对,而且根据上面的流程,我们知道PhoneWindow()是在Application onCreate()之后才生成,那么这个白屏究竟从何而来呢?
理论和实践矛盾,必然是理论出了问题,肯定是哪里有漏洞。就在我百思不得其解的情况下,搜索各方资料以及源码,终于发现了线索:
// android.view.WindowManager.LayoutParams
/**
* Window type: special application window that is displayed while the
* application is s