Android Performance Optimization Part (8) --- Time-consuming detection and processing of App startup speed optimization

Android Performance Optimization Part (8) --- Time-consuming detection and processing of App startup speed optimization

96 
LooperJing 
2016.12.21 11:10*   Word Count 2067   Reads 7852 Comments 2

The slow startup speed of applications is a problem that many developers have encountered, such as black screen and white screen problems caused by slow startup. Most of the answers are to make a transparent theme or make a Splash interface, but this does not does not fundamentally solve the problem. So how to fundamentally solve this problem or achieve a certain degree of mitigation?

1. How to start the application

1. Cold start: When an application is started, there is no process of the application in the background. At this time, the system will first create a new process and assign it to the application. This startup method is a cold start.

2. Hot start: When the application is started, there is a process of the application in the background, such as pressing the home button. In the case of an existing process, this startup will start the application from the existing process. The start method is called warm start.

3. Warm startup: When the application is started, the process of the application already exists in the background, but the startup entry Activity is killed. For example, if the back button is pressed, the application exits, but the application process will still remain in the background. This kind of start method is called warm start.

Second, the application startup time statistics

adb shell am start -W [PackageName]/[PackageName.MainActivity]

A successful execution will return three measured times:

这里面涉及到三个时间,ThisTime、TotalTime 和 WaitTime。WaitTime 是 startActivityAndWait 这个方法的调用耗时,ThisTime 是指调用过程中最后一个 Activity 启动时间到这个 Activity 的 startActivityAndWait 调用结束。TotalTime 是指调用过程中第一个 Activity 的启动时间到最后一个 Activity 的 startActivityAndWait 结束。如果过程中只有一个 Activity ,则 TotalTime 等于 ThisTime。

总结:如果只关心某个应用自身启动耗时,参考TotalTime;如果关心系统启动应用耗时,参考WaitTime;如果关心应用有界面Activity启动耗时,参考ThisTime。

三、性能检查项

从我们Application开始到首页显示出来,这个过程,我们应该注意一些什么,将这个过程细分一下,会有下面的时间点需要注意。

Application的构造器方法——>attachBaseContext()——>onCreate()——>Activity的构造方法——>onCreate()——>配置主题中背景等属性——>onStart()——>onResume()——>测量、布局、绘制显示在界面上。

因为上面这些阶段全部都是在主线程中执行的,任何不经意的操作都可能拖慢应用的启动速度。所以我们不应在Application以及Activity的生命周期回调中做任何费时操作,具体指标大概是你在onCreate,onResume,onStart等回调中所花费的总时间最好不要超过400ms,否则用户在桌面点击你的应用图标后,将感觉到明显的卡顿。但是有些不得以的任务又必须在UI显示之前执行。所以我们要将任务划分优先级。

  • ** 优先级为1的在应用启动时,就开始加载**
  • 优先级为2的在首页渲染完成后,开始加载
  • 优先级为3的在首页渲染完成后,延迟加载

对于首页渲染完成后,开始加载,或者延迟加载,延迟加载的目的就是界面先显示出来,然后加载,但是你觉得要延迟多久呢?在 Android 的高端机型上,应用的启动是非常快的 , 这时候只需要 Delay 很短的时间就可以了, 但是在低端机型上,应用的启动就没有那么快了,而且现在应用为了兼容旧的机型,往往需要 Delay 较长的时间,这样带来体验上的差异是很明显的。延迟加载有一种方式。

  第一种写法:直接PostDelay 300ms.
  myHandler.postDelayed(mLoadingRunnable, DEALY_TIME);
  第二种写法:优化的DelayLoad
  getWindow().getDecorView().post(new Runnable() {
    @Override
   public void run() {
        myHandler.post(mLoadingRunnable);
   }
  });

极力推荐用第二种,在窗口完成以后进行加载,这里面的run方法是在onResume之后运行的。关于这种懒加载机制,参考Android应用启动优化:一种DelayLoad的实现和原理(上篇),给出了详细的解释。

四、利用TraceView逐个修复

通过上面我们知道一种懒加载机制,所以我们可以将Application中和首页的onCreate中的有些耗时任务,放到首页渲染完毕后加载。如何找出这些耗时任务,TraceView就派上用场了,TraceView的用法,移步我的前面的博客Android性能优化第(六)篇---TraceView 分析图怎么看?


比如在首页的onCreate中我们进行了用户启动上报,这个进行懒加载是不是分分钟减少139毫秒呢?


在比如在Application里面用到了GSON,将String转化成json,我将这个移动到懒加载里面,是不是又减少了100毫秒呢?

在比如,有些Application中做了支付SDK的初始化,用户又不会一打开App就要支付,放在Application中加载干嘛?

此处我们这里举得例子是优化了139毫秒和100毫秒的,其实真正耗时的任务有的有1秒多,都被我优化完了,所以trace图中看不到了,就举个了这两个例子,还有SharedPreferences也是耗时大户,经过检测保存一个boolean变量耗时120+毫秒以上。

利用TraceView可以清楚我们每一个方法的耗时时间,极大的帮助了我们做优化工作。

五、优化思路总结
1、UI渲染优化,去除重复绘制,减少UI重复绘制时间,打开设置中的GPU过度绘制开关,各界面过度绘制不应超过2.5x;也就是打开此调试开关后,界面整体呈现浅色,特别复杂的界面,红色区域也不应该超过全屏幕的四分之一;
2、根据优先级的划分,KoMobileApplication的一些初始化工作能否将任务优先级划分成3,在首页渲染完成后进行加载,比如:PaySDKManager。
3、主线程中的所有SharedPreference能否在非UI线程中进行,SharedPreferences的apply函数需要注意,因为Commit函数会阻塞IO,这个函数虽然执行很快,但是系统会有另外一个线程来负责写操作,当apply频率高的时候,该线程就会比较占用CPU资源。类似的还有统计埋点等,在主线程埋点但异步线程提交,频率高的情况也会出现这样的问题。
4、检查BaseActivity,不恰当的操作会影响所有子Activity的启动。
5、对于首次启动的黑屏问题,对于“黑屏”是否可以设计一个.9图片替换掉,间接减少用户等待时间。
6、对于网络错误界面,友好提示界面,使用ViewStub的方式,减少UI一次性绘制的压力。
7、任务优先级为2,3的,通过下面这种方式进行懒加载的方式

  getWindow().getDecorView().post(new Runnable() {
   @Override
   public void run() {
       myHandler.post(mLoadingRunnable);
    }
  });

8、Multidex的使用,也是拖慢启动速度的元凶,必须要做优化。后面有空专门写一篇Multidex。

相关链接:

Android应用启动优化:一种DelayLoad的实现和原理(上篇)http://androidperformance.com/2015/11/18/Android-app-lunch-optimize-delay-load.html

Android性能优化之加快应用启动速度http://www.open-open.com/lib/view/open1452821612355.html

手机淘宝性能优化全记录http://www.open-open.com/lib/view/open1452488209370.html

Android客户端性能优化(魅族资深工程师毫无保留奉献)http://blog.tingyun.com/web/article/detail/155#rd

Please accept mybest wishes for your happiness and success !

欢迎大家给予更大的鼓励

赞赏支持
 Android性能优化
Web note ad 1
登录  后发表评论
 
云舒s
2楼 · 2017.08.01 15:05

getWindow().getDecorView().post(new Runnable() {
@Override
public void run() {
myHandler.post(mLoadingRunnable);
}
});
When the thread is destroyed, the thread for data loading or setting can be mHandler in onDestroy .removeCallbacksAndMessages(null); So what should the thread in the outermost getWindow().getDecorView().post() do?

 
goodness
3rd Floor · 2017.09.07 11:37

Excuse me, when you do this, will a black screen or a white screen appear when the startup page starts? There is, the main interface of lazy loading, where is the bottom navigation bar below, I don't see it in your layout file?

Reprinted from: https://www.jianshu.com/p/a0e242d57360

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325576186&siteId=291194637