Android性能分析之---启动卡顿优化

一、前提

Android studio4.2.2

compileSdkVersion 30

buildToolsVersion "30.0.3"

        在Android中的启动卡顿会导致点击了屏幕的图标,等待很久才会出现响应界面,或者启动的时候出现很长时间的黑屏或者白屏的问题。在优化之前,我们必须得分析找出卡顿的地方,影响我们启动慢的原因。上一篇文章介绍了如何分析Android开发过程中的卡顿问题,不限于启动卡顿。文章地址:Android性能分析之---卡顿分析_sunbinkang的博客-CSDN博客

优化的前提条件就是你得分析出那些地方你能优化,通过工具便可以找出耗时比较长的地方。

二、优化---冷启动

今天我们这篇文章从冷启动的卡顿问题着手去优化。

说到Android的启动,我们就必须大概得知道启动的流程,以便我们更好的更快的找出问题点。

Activity的启动主要涉及四个进程

SystemServer进程:主要负责管理整个Framework

App进程:app用户点击桌面icon时,通过Launcher进程请求SystemServer进程,再通知Zygote孵化的。

Zygote进程:所有的应用进程都是有Zygote孵化出来的,而Zygote进程由init进程孵化出来,init进程的子进程。

扫描二维码关注公众号,回复: 15000584 查看本文章

Launcher 进程 :Zygote进程孵化的第一个应用进程。

Activity的启动主要涉及到七个阶段

第一阶段: Launcher通知AMS要启动新的Activity(在Launcher所在的进程执行)

第二阶段:AMS先校验一下Activity的正确性,如果正确的话,会暂存一下Activity的信息。然后,AMS会通知Launcher程序pause Activity(在AMS所在进程执行)

第三阶段: pause Launcher的Activity,并通知AMS已经paused(在Launcher所在进程执行)

第四阶段:检查activity所在进程是否存在,如果存在,就直接通知这个进程,在该进程中启动Activity;不存在的话,会调用Process.start创建一个新进程(执行在AMS进程,内部通过socket和Zygote通信,fork一个新进程)

第五阶段: 创建ActivityThread实例,执行一些初始化操作,之后进入Loop循环。(执行在新创建的app进程)

第六阶段:处理新的应用进程发出的创建进程完成的通信请求,并通知新应用程序绑定Application。如果Application不存在,会调用LoadedApk.makeApplication创建一个新的Application对象。并且通知进程启动目标Activity组件(执行在AMS进程)

第七阶段: 加载MainActivity类,调用onCreate声明周期方法(执行在新启动的app进程)

        从上面的启动流程分析我们可以得知,我们能着手优化的点主要是我们的application的oncreate生命周期和activity的onCreate或者onResume、onStart等生命周期。其他流程都是Android系统调用,我们一般情况无法干涉到。

优化一、主题切换,解决黑白屏问题

        当系统加载并启动 App 时,需要耗费相应的时间,这样会造成用户会感觉到当点击 App 图标时会有 “延迟” 现象,为了解决这一问题,Google 的做法是在 App 创建的过程中,先展示一个空白页面,Google在配置默认主题的BackgroundWindow默认值为白色或者黑色,让用户体会到点击图标之后立马就有响应。如果你的application或activity启动的过程太慢,导致系统的BackgroundWindow没有及时被替换,就会出现启动时白屏或黑屏的情况(取决于Theme主题是Dark还是Light)。消除启动时的黑/白屏问题,大部分App都采用自己在Theme中设置背景图的方式来解决。


在res的values文件夹下面的styles.xml或者themes.xml添加一个启动主题

<style name="Launcher">
    <item name="android:windowBackground">@drawable/bg</item>
</style>
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/white" />
    <item>
        <bitmap
            android:gravity="center"
            android:scaleType="centerCrop"
            android:src="@drawable/icon_qq_login" />
    </item>
</layer-list>

 

 

 

 总结:这个优化方案其实是治标不治本的,从欺骗用户的角度来产生启动快的错觉。但是总比看到白屏或者黑屏要好一些。

优化二、使用idleHandler延迟处理

实际项目发现友盟和腾讯TBS需要时间较长,在考虑业务的同时,是可以将这些放到cpu空闲后初始化的,所以将这些第三方的初始化都放到了这里。

Looper.myQueue().addIdleHandler {
    // TODO:依赖库的初始化
    false
}

IdleHandler是一个回调接口,可以通过MessageQueue的addIdleHandler添加实现类。当MessageQueue中的任务暂时处理完了(没有新任务或者下一个任务延时在之后),这个时候会回调这个接口,返回false,那么就会移除它,返回true就会在下次message处理完了的时候继续回调。

优化三、布局优化

        减少布局的嵌套层级,使用include、viewStub、meger等标签

优化四、异步加载

        使用异步线程的方式加载一些逻辑,可以使用:RxJava、线程池、AsyncTask、IntentService、HandlerThread、Thread

优化五、懒加载

        例如首页是个viewpager+fragment的话,可以使用懒加载优化

优化六、StrictMode严苛模式

        StrictMode是一个开发人员工具,它可以检测出我们可能无意中做的一些耗时不合理事情,并将它们提醒我们注意,以便我们能够修复它们。StrictMode最常用于捕获应用程序主线程上的文件磁盘或网络访问。帮助我们让磁盘和网络操作远离主线程,可以使应用程序更加平滑、响应更快。

在application的OnCreate方法中设置严苛模式。

fun setStrictMode() {
        if (BuildConfig.DEBUG) {
            //线程检测策略
            StrictMode.setThreadPolicy(
                StrictMode.ThreadPolicy.Builder()
                    .detectDiskReads() //读、写操作
                    .detectDiskWrites()
                    .detectNetwork() // or .detectAll() for all detectable problems
                    .penaltyLog()
                    .build()
            );
            StrictMode.setVmPolicy(
                StrictMode.VmPolicy.Builder()
                    .detectLeakedSqlLiteObjects() //Sqlite对象泄露
                    .detectLeakedClosableObjects() //未关闭的Closable对象泄露
                    .penaltyLog() //违规打印日志 
                    .penaltyDeath() //违规崩溃 
                    .build()
            );
        }
    }

这样能更好的更及时的帮我们找出问题,而不是事后要发布的时候来找这些问题。

三、总结

        性能分析要根据项目的实际情况来分析和优化。性能优化是一个比较耗时的过程,所以我们应该尽量在平时的开发过程中就应该避免这些问题,而不是等要上线发布的时候才来做性能分析和优化,这样反而比平时花点时间注意还更加耗时费力。因此养成好的开发习惯,可以帮助我们更好的成长。

猜你喜欢

转载自blog.csdn.net/sunbinkang/article/details/125128651