一般来讲,启动方式分为两种:冷启动和热启动。html
一、冷启动:当启动应用时,后台没有该应用的进程,这时系统会从新建立一个新的进程分配给该应用,这个启动方式就是冷启动。android
二、热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,可是该应用的进程是依然会保留在后台,可进入任务列表查看),因此在已有进程的状况下,这种启动会从已有的进程中来启动应用,这个方式叫热启动。shell
特色数据库
一、冷启动:冷启动由于系统会从新建立一个新的进程分配给它,因此会先建立和初始化Application类,再建立和初始化MainActivity类(包括一系列的测量、布局、绘制),最后显示在界面上。浏览器
二、热启动:热启动由于会从已有的进程中来启动,因此热启动就不会走Application这步了,而是直接走MainActivity(包括一系列的测量、布局、绘制),因此热启动的过程只须要建立和初始化一个MainActivity就好了,而没必要建立和初始化Application,bash
由于一个应用重新进程的建立到进程的销毁,Application只会初始化一次。网络
冷启动启动流程:当点击app的启动图标时,安卓系统会从Zygote进程中fork建立出一个新的进程分配给该应用: app
应用的第一次启动才算完成,这时候咱们看到的界面也就是所说的第一帧。因此,总结一下,应用的启动流程以下:框架
Application的构造器方法——>attachBaseContext()——>onCreate()——>Activity的构造方法——>onCreate()——>配置主题中背景等属性——>onStart()——>onResume()——>测量布局绘制显示在界面上。 eclipse
大体流程以下:
一、点击桌面图标,Launcher会启动程序默认的Acticity,以后再按照程序的逻辑启动各类Activity
二、启动Activity都须要借助应用程序框架层的ActivityManagerService服务进程(Service也是由ActivityManagerService进程来启动的);在Android应用程序框架层中,ActivityManagerService是一个很是重要的接口,
它不但负责启动Activity和Service,还负责管理Activity和Service。
Step 1. 不管是经过Launcher来启动Activity,仍是经过Activity内部调用startActivity接口来启动新的Activity,都经过Binder进程间通讯进入到ActivityManagerService进程中,而且调用ActivityManagerService.startActivity接口;
Step 2. ActivityManagerService调用ActivityStack.startActivityMayWait来作准备要启动的Activity的相关信息;
Step 3. ActivityStack通知ApplicationThread要进行Activity启动调度了,这里的ApplicationThread表明的是调用ActivityManagerService.startActivity接口的进程,对于经过点击应用程序图标的情景来讲,这个进程就是Launcher了,
而对于经过在Activity内部调用startActivity的情景来讲,这个进程就是这个Activity所在的进程了;
Step 4. ApplicationThread不执行真正的启动操做,它经过调用ActivityManagerService.activityPaused接口进入到ActivityManagerService进程中,看看是否须要建立新的进程来启动Activity;
Step 5. 对于经过点击应用程序图标来启动Activity的情景来讲,ActivityManagerService在这一步中,会调用startProcessLocked来建立一个新的进程,而对于经过在Activity内部调用startActivity来启动新的Activity来讲,这一步是不须要执行的,
由于新的Activity就在原来的Activity所在的进程中进行启动;
Step 6. ActivityManagerServic调用ApplicationThread.scheduleLaunchActivity接口,通知相应的进程执行启动Activity的操做;
Step 7. ApplicationThread把这个启动Activity的操做转发给ActivityThread,ActivityThread经过ClassLoader导入相应的Activity类,而后把它启动起来。 连接
一、将背景图设置成咱们APP的Logo图,做为APP启动的引导,如今市面上大部分的APP也是这么作的:
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
<style name="AppTheme.NoActionBar.Splash">
<item name="android:windowBackground">@drawable/splash_image_1</item>
</style>
复制代码
二、将背景颜色设置为透明色,这样当用户点击桌面APP图片的时候,并不会"当即"进入APP,并且在桌面上停留一会,其实这时候APP已是启动的了,只是咱们原来黑/白屏windowBackground的颜色设置成透明的:
<style name="AppTheme.NoActionBar.Transparent">
<item name="android:windowBackground">@color/transparent</item>
<item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
<item name="android:windowIsTranslucent">true</item>
</style>
复制代码
adb shell am start -W [-D] [PackageName]/[PackageName.MainActivity] 加-D可等待调试器附加到进程 执行成功后将返回三个测量到的时间:
通常而言,热启动时时间较长是由于在MainActivity的onCreate()函数中作了太多UI耗时操做,而冷启动时间较长主要跟Application的onCreate()函数以及MainActivity的onCreate()函数的执行时间有关。 工欲善其事,必先利其器,首先来介绍一下Android测量函数耗时的几个方法:
点击record录制app启动过程当中执行每一个函数及其子函数的CPU耗时,很是直观的能够找到启动过程当中耗时最多的地方。为了捕获到完整的冷启动流程,在开始录制以前先到Android系统设置菜单中选择带调试的应用:
Debug.startMethodTracing(“launch”);
....
代码
.....
Debug.stopMethodTracing();
复制代码
随着程序的运行,在/sdcard/文件夹下会自动建立一个launch.trace的文件,这个文件能够经过Android Studio profiler和eclipse traceView打开,而后进行分析。
二、使用eclipse traceView打开trace文件:
Parents:调用该方法的父类方法
Children:该方法调用的子类方法
若是该方法含有递归调用,可能还会多出两个类别:
Parents while recursive:递归调用时所涉及的父类方法
Children while recursive:递归调用时所涉及的子类方法
至于数据分析面板红色框中,各个字段的含义以下:
三、使用StrictMode线程策略
StrictMode意思为严格模式,是用来检测程序中违例状况的开发者工具,线程策略(ThreadPolicy)检测的内容有
1)自定义的耗时调用 使用detectCustomSlowCalls()开启
2)磁盘读取操做 使用detectDiskReads()开启
3)磁盘写入操做 使用detectDiskWrites()开启
4)网络操做 使用detectNetwork()开启
复制代码
严格模式的开启能够放在Application或者Activity以及其余组件的onCreate方法。为了更好地分析应用中的问题,建议放在Application的onCreate方法中:
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectAll()//开启全部的detectXX系列方法
.penaltyDialog()//弹出违规提示框
.penaltyLog()//在Logcat中打印违规日志
.build());
复制代码
setThreadPolicy()将对当前线程应用该策略。若是不指定检测函数,也能够用detectAll()来替代。penaltyLog()表示将警告输出到LogCat,你也可使用其余或增长新的惩罚(penalty)函数,例如使用penaltyDeath()的话,一旦StrictMode消息被写到LogCat后应用就会崩溃。另外虚拟机策略(VmPolicy)不能经过一个对话框提供警告。
在线程策略(ThreadPolicy)检测的时候,有几个penalty系列方法。
1)penaltyDeath(),当触发违规条件时,直接Crash掉当前应用程序。
2)penaltyDeathOnNetwork(),当触发网络违规时,Crash掉当前应用程序。
3)penaltyDialog(),触发违规时,显示对违规信息对话框。
4)penaltyFlashScreen(),会形成屏幕闪烁,不过通常的设备可能没有这个功能
复制代码
四、使用Android Systrace
Systrace 容许在系统级别收集和检查设备上运行的全部进程的计时信息。 它未来自Android内核的数据(例如CPU调度程序,磁盘活动和应用程序线程)组合起来,以生成HTML报告。若是想分析Android系统或者app的问题,首先咱们须要抓取Systrace文件分析并找出引发系统卡顿,或者app反应慢的缘由,而后在源码上解决引发慢的问题。首先连接手机,打开Android Device Monitor,选择要分析的进程,点击Capture system wide trace using Android。
一、页面布局:
1)当根布局文件最外层标签为FrameLayout以及使用include标签引用的布局文件的最外层标签
能够用merge标签来替换,减小一层布局深度。
2)对于页面中不须要当即展现的部件使用ViewStub实现延迟加载的方式
3)合理运用LinearLayout和RelativeLayout,减小布局嵌套,推荐使用ConstraintLayout
4)当时用自定义控件时,onDraw()中及不要作耗时操做
复制代码
二、应用初始化:
在大部分app开发中,咱们都会去重写Application类,而后在onCreate()里进行一些初始化操做,好比建立一些全局单例,第三方SDK以及一些功能模块的初始化等,若是初始化函数耗时过长,应该放到线程池或者intentService中去操做;涉及到数据库和文件等I/O操做,放到真正须要的地方再执行。一样在MainActivity的onCreate()函数中也要注意上述问题,由于只有当Activity生命周期执行到onResume()函数的时候界面才会真正显示出来,onCreate()函数执行时间越长,界面等待显示的时间越长,若是有些初始化流程必需要放在onCreate()当中,可使用DelayLoad的机制:
getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
myHandler.post(mLoadingRunnable);
}
});
复制代码
ViewRootImpl 的 performTraversals 方法是一个很核心的方法,每一帧绘制都会走一遍,调用各类 measure / layout / draw 等 ,最终将要显示的数据交给 hwui 去进行绘制。Activity 在启动时,会在第二次执行 performTraversals 才会去真正的绘制,缘由在于第一次执行 performTraversals 的时候,会走到 Egl 初始化的逻辑,而后会从新执行一次 performTraversals 。在 onCreate 中 Post 的 runnable 对象,在第一个 performTraversals 方法执行的时候被调用,mLoadingRunnable在界面真正绘制的时候才会执行。