【性能优化】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应用优化之冷启动优化
相关推荐
萌面小侠Plus31 分钟前
Android笔记(三十三):封装设备性能级别判断工具——低端机还是高端机
android·性能优化·kotlin·工具类·低端机
慢慢成长的码农31 分钟前
Android Profiler 内存分析
android
大风起兮云飞扬丶31 分钟前
Android——多线程、线程通信、handler机制
android
L725638 分钟前
Android的Handler
android
清风徐来辽38 分钟前
Android HandlerThread 基础
android
HerayChen2 小时前
HbuildderX运行到手机或模拟器的Android App基座识别不到设备 mac
android·macos·智能手机
顾北川_野2 小时前
Android 手机设备的OEM-unlock解锁 和 adb push文件
android·java
hairenjing11232 小时前
在 Android 手机上从SD 卡恢复数据的 6 个有效应用程序
android·人工智能·windows·macos·智能手机
小黄人软件2 小时前
android浏览器源码 可输入地址或关键词搜索 android studio 2024 可开发可改地址
android·ide·android studio
dj15402252033 小时前
group_concat配置影响程序出bug
android·bug