【性能优化】Android冷启动优化

文章目录


常见现象

各种第三方工具初始化和大量业务逻辑初始化,影响启动时间,导致应用启动延迟、卡顿等现象

APP的启动流程

加载和启动应用程序;

App启动之后立即展示出一个空白的启动窗口;

创建App程序的进程;

创建App对象;

启动Main Thread;

创建启动页的Activity;

加载View;

布置屏幕;

进行初始绘制;

详细启动流程可以看这篇文章
APP启动流程

计算启动时间

看一张官图

上图是Google提供的冷启动流程图,可以看到冷启动的起始点时Application.onCreate()方法,结束点在ActivityRecord.reportLanuchTimeLocked()方法。

我们可以通过以下两种方式查看冷启动的耗时

Displayed Time

在Android 4.4(API级别19)及更高版本中,logcat包含一个名为Displayed的log信息,此值表示启动过程和完成在屏幕上绘制相应活动之间所经过的时间量。

java 复制代码
	adb logcat | grep Displayed
	05-08 19:18:14.303   419   477 I ActivityTaskManager: Displayed ***/.ui.HomeActivity: +1s382ms
	

adb dump

java 复制代码
	adb shell am start -S -W ***/.ui.HomeActivity -c android.intent.category.LAUNCHER -a android.intent.action.MAIN
	
	Stopping: ***
	Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=***/.ui.HomeActivity }
	Status: ok
	LaunchState: COLD
	Activity: ***/.ui.HomeActivity
	TotalTime: 1391
	WaitTime: 1392
	Complete

ThisTime:是指调用过程中最后一个Activity启动时间到这个Activity的 startActivityAndWait调用结束;

TotalTime:是指调用过程中第一个Activity的启动时间到最后一个Activity的 startActivityAndWait结束。

WaitTime:是startActivityAndWait这个方法的调用耗时;

此方法通过终端ADB命令查看启动指定页面(应用首页)的耗时,即应用冷启动的时间。

启动优化具体策略

  1. 启动白屏或黑屏问题
    设置启动页
java 复制代码
<style name="WelcomeTheme" parent="Theme.AppCompat.Light.NoActionBar.FullScreen">
    <item name="android:windowBackground">@drawable/shape_welcome</item>
    <item name="android:windowDrawsSystemBarBackgrounds">false</item>
</style>
  1. Application启动优化
    attachBaseContext()的优化

    主要是MultiDex启动优化的,但是MultiDex启动优化存在一定风险,主dex经过一系列的优化操作减少了主dex的大小,因此也增大了NoClassDefFoundError的异常的可能,此时会导致我们的应用启动失败的风险。所以MultiDex启动优化一定要做好检查测试工作。

    onCreate()

    Application的onCreate()随着业务的复杂会存在大量的第三方库的初始化和组件初始化,导致该生命周期过于沉重,影响启动时间。对onCreate()的优化可以分为四类

    1、必须在onCreate()且是主进程中初始化

    2、可以延迟,但是需要在Application中初始化

    3、可以延迟到启动页的生命周期回调中初始化

    4、延迟到用的时候再初始化

    此处的优化着力会比较多,牵涉的代码业务逻辑比较复杂,核心是减轻冷启动初始化的工作,延迟初始化和按需初始化。

  2. 寻找有效的结束回调

    1、IdleHandler

    从冷启动流程图看,结束时间是在UI渲染完计算的,所以很明显,Activity生命周期中的onCreate()、onResume()、onStart()都不能作为冷启动的结束回调。常规操作中用Handler.postDelay()问题在于Delay的时间不固定,但我们知道消息处理机制中,MessageQueue有个ArrayList。可以在列表中添加Idle任务,Idle任务列表只有MessageQueue队列为空时才会执行,也就是所在线程任务已经执行完时,线程处于空闲状态时才会执行Idle列表中的任务。

java 复制代码
public class MainActivity extends Activity {

    private static final Handler sHandler = new Handler(Looper.getMainLooper());
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
        @Override    
        public boolean queueIdle() {   
            // 页面启动所需耗时初始化            
            doSomething();
            return false;
        }});
    }
}

2、onWindowFocusChanged()

在冷启动结束即UI渲染完在去处理初始化操作,也是达到延迟初始化的目的。

java 复制代码
@Override
    public void onWindowFocusChanged(boolean hasFocus) {    
        super.onWindowFocusChanged(hasFocus);    
        if (onCreateFlag && hasFocus) {
            onCreateFlag = false;
            
            sHandler.post(new Runnable() {
                @Override
                public void run() {
                    doSomething();
                }
            })
        }
    }

3、通过View.post(Runnable runnable)方法实现

View内部维护了一个HandlerActionQueue,我们可以在DecorView attachToWindow前,通过View.post()将任务Runnables存放到HandlerActionQueue中。当DecorView attachToWindow时会先遍历先前存放在HandlerActionQueue的任务数组,通过handler挨个执行。

java 复制代码
  // 方案只有在onResume()或之前调用有效
    protected void postAfterFullDrawn(final Runnable runnable) {    
        if (runnable == null) {        
            return;    
        }    
        getWindow().getDecorView().post(new Runnable() {        
            @Override        
            public void run() {            
                sHandler.post(runnable);
            }    
        });
    }

总结

冷启动优化主要是两大方面一是启动页的设置;而是初始化的管理包含延迟初始化和按需初始化,根本还是减少不必要的初始化逻辑,尽量轻量化。

参考链接

  1. 【性能优化】Android冷启动优化
  2. Android应用优化之冷启动优化
相关推荐
千里马学框架3 天前
一起学 Android 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台3 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone3 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc3 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo3 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077003 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼3 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
liangshanbo12153 天前
React 性能优化实战
性能优化·react
AFinalStone3 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen3 天前
属性动画原理与高级动画实现
android·kotlin·canvas