Android性能优化 - 启动速度优化

  • 做开发除了实现功能,还要注重优化,性能优化包括的东西还是非常多的,包体大小、启动速度、内存、数据结构、ANR、卡顿等等。
  • 用户都希望APP按下,就能马上进入首页使用,手机性能很重要,但不能要求用户换手机,于是我们就需要APP想办法优化启动的速度,不然这APP可能会被删掉。
  • Android性能优化 - 卡顿和布局优化 可以一起学习。

1.启动的状态

  • 我们APP不是微信那种体量,所以几乎不可能有厂商给我们搞特殊,一直挂在那,大多数情况下都是冷启动,优化也是主要优化冷启动。
  • 冷启动
    冷启动是指应用从头开始启动:系统进程在冷启动后才创建应用进程。发生冷启动的情况包括应用自设备启动后或系统终止应用后首次启动。
  • 热启动
    在热启动中,系统的所有工作就是将 Activity 带到前台。只要应用的所有 Activity 仍驻留在内存中,应用就不必重复执行对象初始化、布局加载和绘制。比如回到桌面,不杀掉APP的时间内又回来。
  • 温启动
    温启动包含了在冷启动期间发生的部分操作;同时,它的开销要比热启动高。有许多潜在状态可视
    为温启动。例如:
    1.用户在退出应用后又重新启动应用。进程可能未被销毁,继续运行,但应用需要执行
    onCreate() 从头开始重新创建 Activity。
    2.系统将应用从内存中释放,然后用户又重新启动它。进程和 Activity 需要重启,但传递到
    onCreate() 的已保存的实例 state bundle 对于完成此任务有一定助益。

2.冷启动耗时

  • 2-5-8原则:
  • 当用户能够在2秒以内得到响应时,会感觉系统的响应很快;
  • 当用户在2-5秒之间得到响应时,会感觉系统的响应速度还可以;
  • 当用户在5-8秒以内得到响应时,会感觉系统的响应速度很慢,但是还可以接受;
  • 而当用户在超过8秒后仍然无法得到响应时,会感觉系统糟透了,或者认为系统已经失去响应。

2.1 系统日志统计

  • Logcat,筛选 Displayed,就能看到启动时长。
  • 这个时长就是应用启动到显示对应的Activity绘制完成的时长。(下图就是启动到MainActivity)
    日志查看启动时长

2.2 adb命令统计

  • adb需要配置环境变量,只需要把 sdk 目录下的 platform-tools 路径添加到 环境变量path 里面就行。
    配置adb环境变量

  • adb shell

  • am start -S -W com.bao.myapplication/.MainActivity

  • 根据自己的包名和要启动的Activity输入这两行命令就可以看到启动时间。

  • TotalTime就是启动时长啦。
    adb查看启动时长

3.启动分析

3.1 CPU Profile工具简单教程

  • Android Studio 功能越来越完善,我们可以利用 CPU Profile 来查看分析启动时做了什么事情。

  • 点击 app -> Edit Configurations
    cpu profile

  • Profilling -> Start recording CPU activity on startup

  • 选择CPU记录配置 Trace Java Methods
    选择CPU记录配置

  • 这四种模式官方文档也有详细说明。

  • 1.对 Java 方法采样:在应用的 Java 代码执行期间,频繁捕获应用的调用堆栈。分析器会比较捕获的数据集,以推导与应用的 Java 代码执行有关的时间和资源使用信息。
    基于采样的跟踪存在一个固有的问题,那就是如果应用在捕获调用堆栈后进入一个方法并在下次捕获前退出该方法,分析器将不会记录该方法调用。如果您想要跟踪生命周期如此短的方法,应使用插桩跟踪。

  • 2.跟踪 Java 方法:在运行时检测应用,从而在每个方法调用开始和结束时记录一个时间戳。系统会收集并比较这些时间戳,以生成方法跟踪数据,包括时间信息和 CPU 使用率。
    请注意,与检测每个方法相关的开销会影响运行时性能,并且可能会影响分析数据;对于生命周期相对较短的方法,这一点更为明显。此外,如果应用在短时间内执行大量方法,则分析器可能很快就会超出其文件大小限制,因而不能再记录更多跟踪数据。

  • 3.对 C/C++ 函数采样:捕获应用的原生线程的采样跟踪数据。如需使用此配置,您必须将应用部署到搭载 Android 7.0(API 级别 24)或更高版本的设备上。
    在内部,此配置使用 simpleperf 跟踪应用的原生代码。如果需为 simpleperf 指定其他选项,如对特定设备 CPU 采样或指定高精度采样持续时间,您可以从命令行使用 simpleperf。

  • 4.跟踪系统调用:捕获非常翔实的细节,以便您检查应用与系统资源的交互情况。您可以检查线程状态的确切时间和持续时间、直观地查看所有内核的 CPU 瓶颈在何处,并添加需分析的自定义跟踪事件。当您排查性能问题时,此类信息至关重要。如需使用此配置,您必须将应用部署到搭载 Android 7.0(API 级别 24)或更高版本的设备上。
    使用此跟踪配置时,您可以通过检测代码,在分析器时间轴上直观地标记重要的代码例程。如需检测 C/C++ 代码,请使用由 trace.h 提供的原生跟踪 API。如需检测 Java 代码,请使用 Trace 类。如需了解详情,请参阅检测您的应用代码。

    此跟踪配置建立在 systrace 的基础之上。您可以使用 systrace 命令行实用程序指定除 CPU 性能剖析器提供的选项之外的其他选项。systrace 提供的其他系统级数据可帮助您检查原生系统进程并排查丢帧或帧延迟问题。

  • 设置好了之后就启动Profile。
    启动Profile

  • 当你看到自己APP,CPU的使用率比较低的时候,差不多就是启动完成了,点一下stop。
    在这里插入图片描述

3.2 启动耗时分析

  • Call Chart 双击要看的线程,就能看到从上到下,方法执行的时长,除了系统的方法,绿色是自己的代码,就能看到耗时了,这里的方法是按时间线排列的,从启动到完成的过程。
    Call Chart

  • Top Down标签显示一个调用列表,在该列表中展开方法或函数节点会显示它的被调用方。下图可以看到我在自定义View里面放了一个Thread.sleep,休眠了3秒。
    Top Down

  • Flame Chart火焰图横向代表方法时长,向上就是被调用的方法,我们也能看到自定义View里面的sleep明显比其他长。
    Flame Chart

3.3 使用Debug Api 生成.trace文件

  • 在Application onCreate 方法加入 Debug.startMethodTracing()
  • 在MainActivitu onWindowFocusChanged(boolean hasFocus) 方法加入 Debug.stopMethodTracing()
public class BaoApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        Debug.startMethodTracing("baoTest");
    }
}

public class MainActivity extends AppCompatActivity {
   .
   .
   . 

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        .
        .
        .
    }

    /**
     * MainActivity 停止启动分析的地方
     * @param hasFocus
     */
    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        super.onWindowFocusChanged(hasFocus);
        Debug.stopMethodTracing();
    }
}
  • 默认在自己应用的目录下生成 .trace 文件,复制到自己电脑目录下。
    .trace文件目录
  • 拖到Android Studio,就可以查看结果了。
    拖进去分析

4.StrictMode严苛模式

  • 开发时开启严苛模式,提示我们。
  @Override
    public void onCreate() {
        super.onCreate();
        if (BuildConfig.DEBUG) {
            //线程检测
            StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
                    .detectDiskReads()
                    .detectDiskWrites()
                    .detectNetwork()
                    .penaltyLog()
                    .build());

            StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
                    .detectLeakedSqlLiteObjects()//数据库对象泄漏
                    .detectLeakedClosableObjects()//未关闭的对象泄漏
                    .penaltyDeath()//违规奔溃
                    .penaltyLog()//违规日志
                    .build());
        }
    }

5.结尾

  • 简化布局,布局层级不要太多可以提高启动速度(熟练使用约束布局可以减少层级),启动和主线程不要做耗时操作。
  • 启动尽量别搞什么sleep休眠之类的,就算不报错,但也不好查找。
  • 有的APP会有启动广告,我们可以在展示广告的时间里,利用子线程继续初始化工作。
  • 启动的流程非常的多,也非常复杂,一般我们能改的就是自己的APP,通过工具分析自己的APP哪些地方比较耗时,能减少的尽量减少,有一些减少非常有限,但是项目比较大的时候,往往都是积少成多的,需要一点点去优化。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值