当前位置: 棋牌电玩游戏平台 > 用户体验 > 正文

App启动优化

时间:2019-06-25 02:46来源:用户体验
现在微信小程序火爆异常,各种demo层出不穷,笔者也不免俗,一直有关注,虽然不是微信的死忠,但是不得不佩服微信的野心。开发难度不高再加上微信生态,感觉这个东西正式进入市

现在微信小程序火爆异常,各种demo层出不穷,笔者也不免俗,一直有关注,虽然不是微信的死忠,但是不得不佩服微信的野心。开发难度不高再加上微信生态,感觉这个东西正式进入市场后必定对原生开发造成一定的影响,特别是一些创业公司因为考虑到原生开发的高成本,微信小程序不失为一种高效的途径。建议大家也保持关注,并进行一些基础的尝试。

1.概述

App启动方式,我们通常分为以下两种:

1.冷启动:

启动应用时,系统后台没有该应用的进程,这时系统会为该应用新创建一个进程,这就是我们说的冷启动。冷启动因为系统重新创建一个进程,所以应用创建和初始化Application,然后创建和初始化我们的LaucherActivity类,最终我们的应用显示给用户。

2.热启动:

当应用启动之后,系统后台已经有这个应用的进程,我们按back、home键(关闭应用的那种),应用虽然会退出,但是该应用的进程后台依然会保留,我们打开任务列表会查看到,在已存在相应进程的情况下,laucher启动应用的时候会直接打开该进程,这种方式叫热启动。热启动不会重新创建Application,只会创建和初始化laucherActivity.

这里可以使用命令查看应用启动耗时:

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

一共有三个时间ThisTime、TotalTime、WaitTime,我们只关心应用的自身启动耗时所以只用参考TotalTime。
应用启动到启动页展示出来中间要处理哪些东西呢,我们来简单梳理一下:

1.Application的构造函数

2.attachBaseContext()

3.onCreate()

4.Activity的onCreate()

5.onStart()

6.onResume()

这些都是在我们的主线程中执行,如果在这期间做耗时操作,那么用户就会觉得卡顿,比如点了应用图标,停顿很长时间才首页才显示。优化方式其实很简单,不外乎三种:

1.异步初始化

2.后台任务

3.界面预加载

【触发背景】面对海量APP的今天,APP用户量和活跃度成为评价一款APP是否成功的重要因素。用户下载APP后,APP性能体验比如启动时间,直接影响用户使用频率,甚至决定是否卸载APP。想和大家分享【APP性能关于启动时间】的资料和心得。

要对App进行启动优化,需要了解几个概念。

好了,言归正传。最近公司的一款产品应为启动时间过长,所以做了一定的优化,而笔者有幸参与,现在主要记录一下实践过程。

异步初始化

可以吧一些三方库的初始化放在线程中,比如:

new Thread(){
            @Override
            public void run() {
                //初始化第三方SDK
            }
}.start();

一、APP启动方式

  • 冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动。冷启动因为系统会重新创建一个新的进程分配给它,所以会先创建和初始化 Application 类,再创建和初始化 MainActivity 类,最后显示在界面上。

通常来说,启动方式分为两种:冷启动和热启动。

后台Service

利用Service初始化其实和异步初始化道理是一样的,使用IntentService执行完初始化操作之后,自行结束。

Application中的使用

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        InitializeService.start(this);
    }
}

public class InitializeService extends IntentService {
    private static final String ACTION_INIT_WHEN_APP_CREATE = "com.xxxx";
    public InitializeService(String name) {
        super(name);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        if (intent != null) {
            final String action = intent.getAction();
            if (ACTION_INIT_WHEN_APP_CREATE.equals(action)) {
                init();
            }
        }
    }
    private void init() {
        //初始化第三方SDK
    }
    public static void start(Context context) {
        Intent intent = new Intent(context, InitializeService.class);
        intent.setAction(ACTION_INIT_WHEN_APP_CREATE);
        context.startService(intent);
    }
}

通常来说,APP中启动方式分为两种:冷启动和热启动。
1.冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动。

1、冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,这个启动方式就是冷启动。

界面预加载

Application中的耗时我们做了优化,但是启动页Activity的onCreate()的耗时我们也要考虑,为了让用户有个好的体验,我们会设置一些闪屏页。这个其实并不是真正优化App的启动时间,只是给用户感觉上的点击图标立马看到了我们的页面,启动变快了。
我们可以用一张图片或者layer-list作为背景,设置为首页的Theme,Android系统在执行Activity的onCreate()方法之前会先读取Theme主题进行相关绘制。

<style name="SplashStyle" parent="AppTheme">
        <item name="android:windowBackground">@drawable/splash_pic</item>
</style>

给启动页Activity设置这个Theme。

我们的应用一般都设置有启动页,启动页一般用来展示广告,启动页可以用Fragment或者View代替,用户最终是为了看到MainActivity,这样做的话在用户以为的启动页打开的时候,我们已经绘制完成MainActivity了,这样也是启动优化的一种方式

特别注意SharedPreference的使用,相关疑问请参考请不要滥用SharedPreference

主页Activity的UI避免过度绘制这个我们在界面优化中再详细的说明。

2.热启动:当启动应用时,后台已有该应用的进程(例:按back键/home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动应用,这个方式叫热启动。

  • 热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动应用,这个方式叫热启动。热启动因为会从已有的进程中来启动,所以热启动就不会走 Application 这步了,而是直接走 MainActivity,所以热启动的过程不必创建和初始化 Application,因为一个应用从新进程的创建到进程的销毁,Application 只会初始化一次。

  • 首次启动:首次启动严格来说也是冷启动,之所以把首次启动单独列出来,一般来说,首次启动时间会比非首次启动要久,首次启动会做一些系统初始化工作,如缓存目录的生产,数据库的建立,SharedPreference的初始化,如果存在多 dex 和插件的情况下,首次启动会有一些特殊需要处理的逻辑,而且对启动速度有很大的影响,所以首次启动的速度非常重要,毕竟影响用户对 App 的第一映像。

2、热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动应用,这个方式叫热启动。

请注意:上面说的启动是点击app的启动图标来启动的,而另外一种方式是进入最近使用的列表界面来启动应用,这种不应该叫启动,应该叫恢复。

查看启动时间

  • log日志里,正则过滤出Displayed,需要在NoFilters下
![](https://upload-images.jianshu.io/upload_images/3070482-581fa23613fe19dc.png)

image.png
  • 命令行直接启动
adb shell am start -W lilun.com.pensionlife/.ui.welcome.SplashActivity
//adb shell dumpsys activity activities  获取当前界面的activity名

图片 1

image.png

上图中注意三个时间ThisTime、 TotalTime、 WaitTime,该次为冷启动,热启动只有60 ms;
简单地说
● ThisTime: 最后一个启动的Activity的启动耗时
● TotalTime: 自己的所有Activity的启动耗时
● WaitTime: ActivityManagerService启动App的Activity时的总时间(包括当前Activity的onPause()和自己Activity的启动)

可以从源码里frameworksbasecmdsamsrccomandroidcommandsamAm.java文件中查看到上面时间的计算方法;

本文所指的优化针对冷启动。简单解释一下App的启动过程:

以Android系统举例

启动优化

启动优化主要是指冷启动的优化,冷启动原理有时间再分析;通常在从Launcher界面点击App图标到显示黑白屏之前的这段时间是不可优化的。
通过一些小技巧来对冷启动时间进行优化,从而让你app加载变得”快“一些(视觉体验上的快)。
比如启动黑白屏的问题;
再比如在Application的onCreate里面进行过多的初始化;

  • 出现黑白屏的原因及解决方法
    http://www.cnblogs.com/sunzn/p/3407078.html

  • Application的onCreate里面进行过多的初始化
    通过以下几个方面:延迟初始化、后台任务、界面预加载,减少应用启动时的耗时;

下面onCreate里分析各个初始化函数的耗时,通过trace文件;

  File file = new File(Environment.getExternalStorageDirectory(), "app");
  Log.i("App", file.getAbsolutePath());
  Debug.startMethodTracing(file.getAbsolutePath());
    ... //此处即为初始化代码
  Debug.stopMethodTracing();

当上段文件运行之后,会在getAbsolutePath()目录下生成app.trace文件。
通过adb pull 命令将其取出至电脑中

图片 2

image.png

将此文件拖入Android Stdio中,从中查看比较耗时的操作,看能否优化。

图片 3

image.png

1.点击Launcher,启动程序,通知ActivityManagerService

冷启动:冷启动后系统会重新创建一个新的进程分配给它,所以先创建和初始化Application类,再创建和初始化MainActivity类(包括一系列的测量、布局、绘制),最后经过渲染显示在app界面。
热启动:热启动因为会从已有的进程中来启动,所以热启动就不会走Application这步了,而是直接走MainActivity(包括一系列的测量、布局、绘制),所以热启动的过程只需要创建和初始化一个MainActivity就行了,而不必创建和初始化Application,因为一个应用从新进程的创建到进程的销毁,Application只会初始化一次。

2.ActivityManagerService通知zygote进程孵化出应用进程,分配内存空间等

Android系统上,APP无进程状态,启动流程见下:
Application的构造器方法 ——>attachBaseContext() ——>onCreate() ——>Activity的构造方法 ——>onCreate() ——>配置主题中背景等属性 ——>onStart() ——>onResume() ——>测量布局绘制显示在界面上。

3.执行该应用ActivityThread的main()方法

当点击APP的启动图标时,安卓系统会从Zygote进程中fork创建出一个新的进程分配给该应用,之后会依次创建和初始化Application类、创建MainActivity类、加载主题样式Theme中的windowBackground等属性设置给MainActivity以及配置Activity层级上的一些属性、再inflate布局、当onCreate/onStart/onResume方法都走完了后最后才进行contentView的measure/layout/draw显示在界面上,所以直到这里,应用的第一次启动才算完成,这时候我们看到的界面也就是所说的第一帧。

4.应用程序通知ActivityManagerService它已经启动,ActivityManagerService保存一个该应用的代理对象,ActivityManagerService通过它可以控制应用进程

Android启动流程原理详情请点击这里

5.ActivityManagerService通知应用进程创建入口的Activity实例,执行它的生命周期

二、什么是启动时间?
1.冷启动时间
当用户点击目标app图标的 timepoint到显示界面第一帧的时间段(当用户点击你的app那一刻到系统调用Activity.onCreate()之间的时间段)
在这个时间段内,WindowManager会先加载app主题样式中的windowBackground做为app的预览元素,然后再真正去加载activity的layout布局。

启动过程中Application和入口Activity的生命周期方法按如下顺序调用:

2.热启动时间
用户把目标app切换至后台后,点击app图标的timepoint到显示界面第一帧的时间段

1.Application 构造方法

3.过程
首先我们要知道当打开一个Activity的时候发生了什么,在一个Activity打开时,如果该Activity所属的Application还没有启动,那么系统会为这个Activity创建一个进程(每创建一个进程都会调用一次Application,所以Application的onCreate()方法可能会被调用多次),在进程的创建和初始化中,势必会消耗一些时间,在这个时间里,WindowManager会先加载APP里的主题样式里的窗口背景(windowBackground)作为预览元素,然后才去真正的加载布局。如果加载windowBackground时间过长,而默认的背景又是黑色或者白色,这样会给用户造成一种错觉,APP不流畅,影响用户体验。

2.attachBaseContext()

【补充解释】WindowManager:Windows Manager是一款窗口管理终端,可以远程连接到Linux的X桌面进行管理,与服务器端产生一个session相互通信。详情请点击这里

3.onCreate()

三、使用命令获得启动时间

4.入口Activity的对象构造

使用命令获得启动时间
$adb shell am start -W -n packagename/packageName.MainActivity

编辑:用户体验 本文来源:App启动优化

关键词: 日记本 Android小黑屋