【性能优化】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应用优化之冷启动优化
相关推荐
bianshaopeng1 小时前
android 原生加载pdf
android·pdf
hhzz1 小时前
Linux Shell编程快速入门以及案例(Linux一键批量启动、停止、重启Jar包Shell脚本)
android·linux·jar
火红的小辣椒2 小时前
XSS基础
android·web安全
勿问东西4 小时前
【Android】设备操作
android
五味香4 小时前
C++学习,信号处理
android·c语言·开发语言·c++·学习·算法·信号处理
图王大胜6 小时前
Android Framework AMS(01)AMS启动及相关初始化1-4
android·framework·ams·systemserver
工程师老罗8 小时前
Android Button “No speakable text present” 问题解决
android
小雨cc5566ru9 小时前
hbuilderx+uniapp+Android健身房管理系统 微信小程序z488g
android·微信小程序·uni-app
小雨cc5566ru10 小时前
微信小程序hbuilderx+uniapp+Android 新农村综合风貌旅游展示平台
android·微信小程序·uni-app