Android 性能优化——APP启动优化

这篇具有很好参考价值的文章主要介绍了Android 性能优化——APP启动优化。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

 一、APP启动流程

        首先在《Android系统和APP启动流程》中我们介绍了 APP 的启动流程,但都是 FW 层的流程,这里我们主要分析一下在 APP 中的启动流程。要了解 APP 层的启动流程,首先要了解 APP 启动的分类。

1、启动分类

冷启动

        应用从头开始启动,即应用的首次启动。需要做大量的工做,耗费的时间最多。

热启动

        当活动有驻留在内存中,系统只是把该活动放到前台,无需重复对象初始化、布局扩充和呈现。例如按了home键,相对于冷启动,开销较低。

温启动

        用户退出应用程序,随后又从新启动,可是活动的进程是有驻留在后台的。例如按了back键退出应用。

2、生命周期

冷启动

        对于冷启动的耗时计算比较复杂,除了 Activity 本身的生命周期外,还要考虑 Application onCreate 的耗时操作。所以对于冷启动来说,一般从进程创建(即 Application 的attachBaseContext 方法)开始计时,到完成视图的第一次绘制(即 Activity 的 onWindowFocusChanged 方法)停止计时。

        冷启动 Activity 生命周期:

onCreate() -> onStart() -> onResume() -> onWindowFocusChanged()

热启动

         相比于冷启动,热启动省去了 Application 的初始化,以及 Activity 的 onCreate。热启动生命周期:

Home:onPause() -> onStop()

热启动:onStart() -> onResume()

温启动 

        温启动生命周期:

Back:onPause() -> onStop() -> onDestory()

热启动:onCreate() -> onStart() -> onResume()

        可以看到温启动相比热启动,Activity 生命周期增加了一个 onCreate() 方法,在使用 Back 时也比 Home 多执行一个 onDestory()。

二、启动时间统计

1、埋点统计

        根据上面的生命周期,在不同方法中打印当前时间,通过查看 Log 计算不通启动方式的启动耗时。

2、查找Log

        通过查找 Log 关键字 Displayed 查看 APP 入口信息,即包含启动时间。

adb命令

adb logcat | grep "Displayed"

结果输出

I/ActivityManager( 384): Displayed com.test.myapp/com.test.myapp.MainActivity: 1734 ms (total 1734 ms)

3、adb命令统计

adb shell am start -W 包名/启动类的全限定名

实际使用

adb shell am start -W com.test.myapp/com.test.myapp.MainActivity

        冷启动需要杀掉最近任务进程,再使用上面的命令。热启动需要 Home 键退出应用后使用上面命令。

结果输出

Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.test.myapp/.MainActivity }
Warning: Activity not started, its current task has been brought to the front
Status: ok
LaunchState: HOT
Activity: com.test.myapp/.MainActivity
ThisTime: 79
TotalTime: 79
WaitTime: 82
Complete

LaunchState:启动方式 COLD(冷启动)、 HOT(热启动)和 WARM(温启动)。

ThisTime:启动多个 Activity 的最后一个 Activity 的启动耗时。

TotalTime:启动多个 Activity 总耗时,包括新进程的启动和 Activity 的启动。也就是说,开发者一般只要关心 TotalTime 即可,这个时间才是自己应用真正启动的耗时。

WaitTime:应用进程的创建过程 + TotalTime,就是总的耗时,包括前一个应用 Activity pause 的时间和新应用启动的时间。

        如果只关心某个应用自身启动耗时,参考TotalTime;如果关心系统启动应用耗时,参考WaitTime;如果关心应用有界面Activity启动耗时,参考ThisTime。

多次测试

adb shell am start -S -R 10 -W com.test.myapp/com.test.myapp.MainActivity

        其中 -S 表示每次启动前先强行停止,-R表示重复测试次数,注意反斜杠、包名、类名。所以可以通过 -S 设置冷/热启动。

三、方法耗时统计

        traceview 统计可以用代码统计。也可以用 Android Studio自带的 cup profiler 来统计。

1、Debug Trace

@Override
public void onCreate() {
    super.onCreate();
    Debug.startMethodTracing("main_trace");
    ……
    Debug.stopMethodTracing();
}

        生成文件路径:storage/emulated/0/Android/data/packagename/files/main_trace。

        然后直接将该文件拖入到 Android Studio 中,就能看到对应方法执行的时长,从而进行相关的优化,如是否可以在异步线程操作该方法或者考虑懒加载的方式,根据自己的业务找到合适的方法。

2、CPU Profiler

        Profiler 是 Android Studio 内置的工具。如下配置:

1)run -> edit configurations;
2)勾选start recording a method trace on startup;
3)从菜单中选择cpu记录配置(profiling菜单下勾选两个复选框);
4)apply --> profile模式部署。

详细使用参考:Android app的启动优化总结

3、systrace

@Override
public void onCreate() {
  super.onCreate();
  Trace.beginSection("Launcher");
  ……
  Trace.endSection();
}

        命令行终端进入如下目录:

/Users/tian/Library/Android/sdk/platform-tools/systrace 

        输入如下命令进入监听状态:

    python systrace.py -o main_trace sched freq idle am wm gfx view binder_driver hal dalvik camera input res

        此时运行代码,完成之后在命令行窗口按 Enter 键结束监听,然后会生成目标文件 main_trace,同样使用 Android Studio 的 Profiler 工具进行分析。

三、优化策略

1、优化onCreate, onStart,onResume函数

        由于许多内容在 Activity 的 UI 初始化和生命周期中需要用到,所以大部分 Activity 中的成员需要在 onCreate 中通过 new 的方式赋值。这就要求 new 的类的构造函数应该尽可能简单,不要有耗时操作,以便快速执行。

        不要在这些函数中 new 暂时用不到的内容,比如一些提醒的 dialog,可以在需要提醒的地方再去创建。

2、优化布局文件

        减少UI的布局嵌套层数,从而减少 layout 时间。 简化XML布局,界面布局时,层次越多,加载的时间就越长。因此应该尽可能的减少布局层次。如果实在层次太多并且无法简化,建议不使用XML布局,直接在代码中进行布局。

        判断嵌套布局是否可以优化的方法:

1)借助工具Hierarchy Viewer,可以看到layout比较耗时的节点。

2)直接review xml布局文件。

        布局优化方案:

1)尽量使用 ConstraintLayout 和 RelativeLayout 替换 LinearLayout。

2)尽量为所有分辨率创建资源,减少不必要的硬件缩放,这会降低UI的绘制速度。

3)首次不需要显示的节点,尽量设置为GONE。

3、优化draw过程

        去掉不必要的背景,比如如果子节点和父节点size一样,那么父节点的background可以不设或者设为null。

        尽可能少用或者不用高质量图片,以提高运行效率。

4、优化数据访问

        有些属性需要在 onCreate 就获取,而这些属性保存在 ContentProvider 中。可以从下面两方面进行优化:

1)少用 cursor.getColumnIndex。可以在建表的时候用 static 变量记住某列的 index,直接调用相应index而不是每次查询。

2)查询时返回更少的结果集及更少的字段。只返回需要的字段和结果集,更多的结果集和字段会消耗更多的时间及内存。

5、优化自定义控件或UI部件

        自定义控件和UI部件,不管这些控件是否支持 xml 化,实现它们的代码质量很重要,要尽可能简化它们的构造过程。

6、代码方面的优化

1)使用缓存。尽量将需要频繁访问或访问一次消耗较大的数据存储在缓存中。

2)使用多线程。比较耗时的过程,尽可能的使用异步加载。避免UI主线程阻塞,发生长时间不响应。

3)只需要获取图片的高宽时,可以设置 InJustDecodeBounds 为 true。这样就不会去 decode 图片,减少了图片解析的时间。

4)判断语句如果较多时,尽量使用 switch..case..,而不是使用 if..else..。因为 if..else.. 是从上到下进行判断,而 switch..case.. 有对判断条件进行优化。

5)for() 循环中有 if() 判断,考虑实现为将 if() 判断语句放在 for() 语句外面,减少判断次数,for 语句可以快速执行。

6)String的拼接尽量使用io流。

7)数据类型和数据结构的选择。比如:hash 系列数据结构查询速度更优,ArrayList 存储有序元素。

7、延迟执行

        对于 onCreate, onStart,onResume 函数中的数据或变量初始化,不着急使用的可以放到使用时在进行初始化,或者放到子线程中处理。

8、空闲时间利用

        合理利用程序的空闲时间,等待页面都完全渲染完毕之后再执行。例如:使用IdleHandler,具体使用如下:

Looper.myQueue().addIdleHandler(new MessageQueue.IdleHandler() {
    @Override
    public boolean queueIdle() {
        // 执行你的任务
        return false;
    }
});

        空闲时执行多个任务:

public class DelayTaskQueue {
    private final Queue<Runnable> mDelayTasks = new LinkedList<>();
    
    private final MessageQueue.IdleHandler mIdleHandler = () -> {
        if (mDelayTasks.size() > 0) {
            Runnable task = mDelayTasks.poll();
            if (task != null) {
                task.run();
            }
        }
        // mDelayTasks非空时返回ture表示下次继续执行,为空时返回false系统会移除该IdleHandler不再执行
        return !mDelayTasks.isEmpty();
    };

    public DelayTaskQueue addTask(Runnable task) {
        mDelayTasks.add(task);
        return this;
    }

    public void start() {
        Looper.myQueue().addIdleHandler(mIdleHandler);
    }
}

9、锁优化 

        锁是我们解决并发的重要手段,但是如果滥用锁的话,很可能造成执行效率下降,更严重的可能造成死锁等无法挽回的场景。

        当我们需要处理高并发的场景时,同步调用尤其需要考量锁的性能损耗:

1)能用无锁数据结构,就不要用锁。

2)缩小锁的范围。能锁区块,就不要锁住方法体;能用对象锁,就不要用类锁。

10、内存优化 

        内存优化的核心是避免内存抖动。不合理的内存分配、内存泄漏、对象的频繁创建和销毁,都会导致内存发生抖动,最终导致系统的频繁 GC。

1)解决应用的内存泄漏问题。这里我们可以使用LeakCanary 或者 Android Profile 等工具来检查我们查询可能存在的内存泄漏。平时编码应当注意避免内存泄漏。

2)如避免全局静态变量和常量、单例持有资源对象(Activity,Fragment,View等),资源使用完立即释放或者recycle(回收)等。

3)避免创建大内存对象,频繁创建和释放对象(尤其是在循环体内),频繁创建的对象需要考虑复用或者使用缓存。

4)加载图片可以适当降低图片质量,小图标尽量使用SVG,大图/复杂的图片考虑使用webp。尽量使用图片加载框架,如glide,这些框架都会帮我们进行加载优化。

5)避免大量bitmap的绘制。

6)避免在自定义View的onMeasure、onLayout和onDraw中创建对象。

7)使用 SpareArray、ArrayMap 替代 HashMap。

8)避免进行大量的字符串操作,特别是序列化和反序列化。不要使用+(加号)进行字符串拼接。

9)使用线程池(可设置适当的最大线程池数)执行线程任务,避免大量Thread的创建及泄漏。

11、线程优化

        当我们创建一个线程时,需要向系统申请资源,分配内存空间,这是一笔不小的开销,所以我们平时开发的过程中都不会直接操作线程,而是选择使用线程池来执行任务。所以线程优化的本质是对线程池的优化。

 12、IO优化

        IO优化的核心是减少IO次数。

网络请求优化

1)避免不必要的网络请求。对于那些非必要执行的网络请求,可以延时请求或者使用缓存。

2)对于需要进行多次串行网络请求的接口进行优化整合,控制好请求接口的粒度。比如后台有获取用户信息的接口、获取用户推荐信息的接口、获取用户账户信息的接口。这三个接口都是必要的接口,且存在先后关系。如果依次进行三次请求,那么时间基本上都花在网络传输上,尤其是在网络不稳定的情况下耗时尤为明显。但如果将这三个接口整合为获取用户的启动(初始化)信息,这样数据在网络中传输的时间就会大大节省,同时也能提高接口的稳定性。

磁盘IO优化 

1)避免不必要的磁盘IO操作。这里的磁盘IO包括:文件读写、数据库(sqlite)读写和SharePreference等。

2)对于数据加载,选择合适的数据结构。可以选择支持随机读写、延时解析的数据存储结构以替代 SharePreference。

3)避免程序执行出现大量的序列化和反序列化(会造成大量的对象创建)。

参考:Android APP启动速度优化文章来源地址https://www.toymoban.com/news/detail-849042.html

到了这里,关于Android 性能优化——APP启动优化的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Android】AMS(三)APP启动流程

    在 Android 系统中,启动一个应用程序可以分为三种启动方式: 热启动 、 冷启动 和 温启动 。它们分别表示了不同的启动方式和启动过程。 热启动 热启动是指在已经打开并处于后台运行的应用程序中,再次通过图标进入应用程序的启动方式。这时应用程序的进程已经存在,

    2024年02月08日
    浏览(45)
  • 【Android】APP启动优化学习笔记

    用户体验: 应用的启动速度直接影响用户体验。用户希望应用能够快速启动并迅速响应他们的操作。如果应用启动较慢,用户可能会感到不满,并且有可能选择卸载或切换到竞争对手的应用。通过启动优化,可以提高应用的启动速度,让用户获得更好的使用体验。 竞争优势

    2024年02月14日
    浏览(41)
  • Android S从桌面点击图标启动APP流程 (六)

    系列文章 Android S从桌面点击图标启动APP流程 (一) Android S从桌面点击图标启动APP流程 (二) Android S从桌面点击图标启动APP流程 (三) Android S从桌面点击图标启动APP流程 (四) Android S从桌面点击图标启动APP流程 (五) Android 12的源码链接: android 12 aosp http://aospxref.com/android-12.0.0_r3/ 上文

    2024年02月06日
    浏览(47)
  • 安卓进阶(一)App性能优化

    性能优化的目的是为了让应用程序App 更快、更稳定 更省。具体介绍如下: 更快:应用程序 运行得更加流畅、不卡顿,能快速响应用户操作 更稳定:应用程序 能 稳定运行 解决用户需求,在用户使用过程中不出现应用程序崩溃(Crash) 和 无响应(ANR)的问题 更省:节省耗费

    2024年02月07日
    浏览(48)
  • Android APP开机启动,安卓APP开发自启动,安卓启动后APP自动启动 Android让程序开机自动运行APP

    第一步设置获取广播后的业务 第二查权限给APP 理论以上两步做完就可以了。APP也能收到广播信息了, 但是APP没有在桌面启动。 经过再研究,发现要在手机再设置自动开启等业务,以下是小米、魅族的系统设置的一些内容,其它平台自己研究。 这里已经显示收到广播信息  

    2024年02月06日
    浏览(57)
  • Android APP性能及专项测试

      Android性能测试分为两类: 1、一类为rom版本(系统)的性能测试 2、一类为应用app的性能测试 Android的app性能测试包括的测试项比如: 1、资源消耗 2、内存泄露 3、电量功耗 4、耗时 5、网络流量消耗 6、移动终端相关资源利用率 7、帧率 8、渲染等等.... 工具: (工具的原理

    2024年02月16日
    浏览(54)
  • 开机自启动android app

    Android App开机自启动_android 开机自启动-CSDN博客 注意权限问题: 第二种实现方式: 系统桌面应用 问: android的系统桌面应用启动是什么: 答: Android 系统桌面应用是指用户在设备主屏幕上看到的默认启动界面,也称为 \\\" Launcher \\\"。它是 Android 系统的一部分,用于显示应用程序

    2024年01月21日
    浏览(41)
  • Android/iOS APP备案流程

    工业和信息化部(工信部)全面调研我国移动互联网应用程序(简称APP)的有关情况,在广泛征集APP主办者等互联网信息服务提供者、网络接入服务提供者、应用分发平台、智能终端生产企业等各方意见的基础上,组织开展APP备案工作,着力提升对APP监管效能,促进互联网行业

    2024年02月05日
    浏览(46)
  • Android PMS APP安装流程

    仓库网址:http://androidxref.com/9.0.0_r3/xref/frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java PMS处理安装HandlerParams安装参数流程图 PackageManagerService.java#installStage方法介绍 1、创建了一个InstallParams对象 2、创建并发送了一个INIT_COPY的Message消息。 3、InstallParams继承自

    2024年02月10日
    浏览(45)
  • Android获取App冷启动、热启动时间

    启动模拟器或者连接手机,通过adb命令的方式获取App冷启动、热启动时间。 启动App的adb命令: -W:启动完成之后,返回启动耗时。 比如,我的packagename是com.example.myapplication,我的MainActivity的配置如下: 则adb启动命令为 一、冷启动时间(如果应用启动过,则从最近任务杀进程

    2024年02月05日
    浏览(79)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包