Android优化一些收藏虚拟机/内存/调优

Android App启动优化

2022-03-03  本文已影响0人  mumuxi_

目录:

一、App启动方式

二、App启动时间度量

三、启动优化辅助工具

四、优雅获取方法耗时

五、App启动速度优化


一、App启动方式

冷启动:App启动前,该App进程还没有创建,例如在安装后的第一次启动、设备重启或者应用被杀死情况下发生。

热启动:当App启动时,后台已经有该App的进程,例如按Home键退出App。热启动因为会从已有的进程中来启动,不会再走Application的初始化了。

温启动:介于冷启动和温启动之间,有许多潜在状态可视为温启动。例如

这个温启动的概念有些文章会有,但是并不重要,因为我们优化App启动速度是针对冷启动而言的。

这三种概念详细请看官方文档 https://developer.android.google.cn/topic/performance/vitals/launch-time#cold

二、App启动时间度量

1、adb shell方式:
通过adb命令执行am命令启动App并出界应用启动时间。

命令格式:

adb shell am start -W packagename/packagename.首页Activity

示例:

adb shell am start -W com.example.demoapp/com.example.demoapp.MainActivity2

结果:

➜ DemoApp adb shell am start -W com.example.demoapp/com.example.demoapp.MainActivity2
Starting: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.example.demoapp/.MainActivity2 }
Status: ok
Activity: com.example.demoapp/.MainActivity2
ThisTime: 967
TotalTime: 967
WaitTime: 1011
Complete

ThisTime:表示一连串启动 Activity 的最后一个 Activity 的启动耗时;

TotalTime:表示新应用启动的耗时,包括新进程的启动和 Activity 的启动,但不包括前一个应用Activity pause的耗时。

WaitTime:返回从 startActivity 到应用第一帧完全显示这段时间. 就是总的耗时,包括前一个应用 Activity pause 的时间和新应用启动的时间;

2.adb logcat 方式
Android 4.4之后,Android在系统Log中添加了Display的log信息,可以通过过滤ActivityManager(或者是ActivityTaskManager,跟android版本有关,源码做了改动)关键字,抓取logcat 中的启动时间信息。注意这里的时间不包括数据的加载,因为很多应用在加载时会启动懒加载模式,技术局获取会后再刷新显示UI,所以如果需要获取全部时间包括数据加载时间,需要在你的activity代码的数据加载完的回调函数中加上 reportFullDrawn()。最终抓的logcat 的信息会如下图所示。

1651665689(1).png

3.手动打点计时
启动时埋点,启动结束埋点,二者差值
建一个 LaunchTimer 类来记录APP启动和结束的时间差

import android.util.Log;

public class LauncherTimer {

    private static long time;

    public static void startRecord() {
        time = System.currentTimeMillis();
    }

    public static void endRecord(String msg) {
        long cost = System.currentTimeMillis() - time;
        Log.d("LauncherTimer", msg + " cost time = " + cost);
    }

}

在 Application 的 attachBaseContext(attachBaseContext 是应用启动过程中我们所能接触到第一个方法) 方法中记录启动开始时间,如下所示

import android.app.Application;
import android.content.Context;
import com.mumuxi.testapplication.android.utils.LauncherTimer;

public class MyApplication extends Application {

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        LauncherTimer.startRecord();
    }

    @Override
    public void onCreate() {
        super.onCreate();   
    }


}

在记录APP启动结束时间是可以在 onWindowFocusChanged 方法中记录。onWindowFocusChanged是Activit的首帧时间,是activity首次绘制的时间。不过如果有时候有重要视图需要数据延迟加载后再显示的话,可以选择在数据加载后,第一次显示UI时再记录APP启动结束时间。毕竟我们是为了改善用户的体验,并不是单纯的为了把启动时间缩短,数据延迟加载导致的重要视图未显示这一点也在我们的优化范围内。

如果是列表展示的情况,我们可以选择在真实数据展示,Feed 第一条展示出来,记录启动结束时间。如下所示:

public class NewsAdapter extends RecyclerView.Adapter<NewsAdapter.ViewHolder> {
    /**
     * 是否已经统计过
     */
    private boolean mHasRecorded;

    @Override
    public void onBindViewHolder(@NonNull final ViewHolder holder, int position) {
        //onBindViewHolder 回调多次,而只统计一次,加个变量标识
        if (position == 0 && !mHasRecorded) {
            mHasRecorded = true;
            holder.layout.getViewTreeObserver()
                    .addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                        @Override
                        public boolean onPreDraw() {
                            holder.layout.getViewTreeObserver().removeOnPreDrawListener(this);
                            LauncherTimer.endRecord("FeedShow");
                            return true;
                        }
                    });
        }
    }
}

三、启动优化工具

1.Android Studio CPU Profile(推荐使用,方便快捷)

第一步:如图点击选择Edit Configurations


第二步:如图选择:(第一步后弹出如下框进行相关选择)


相关解释:Java/Kotlin Method Sample :对Java方法进行采样有可能某个方法采集不到,所以选择 Java/Kotlin Method Trace(跟踪采样)

第三步:如图选择Profile app运行


第四步 :App已经运行到我们想要的效果后,点击stop, 运行结束 如图



第五步进行分析:
详细请参考 Android Studio CPU profiler性能分析工具介绍和使用详解

四、优雅获取方法耗时

我们在做启动优化的时候通常需要知道启动阶段所有方法的耗时,这样可以有针对性的分析出耗时较多的方法。通过一些工具我们是可以查看到方法的耗时,但是通过工具我们无法做到直观的两组优化前后的各方法耗时的数据对比。启动优化工具只是帮助我们看到哪些方法耗时,整个调用链是怎么样的,这样我们就能从中找到优化点在哪里。找到优化点后,我们再自动记录优化前后的各个方法的耗时,保存起来导出excel 来直观地对比。

对于一般的获取方法的耗时的方式是通过手动埋点来实现,然后我们可以把这些数据记录到文件中,然后再做对比。比如在某个方法开始和结束的位置分别插入以下代码:

long time = System.currentTimeMillis();
initJpush();
long cost = System.currentTimeMillis() - time;

当有多个方法需要埋点时,同理这样写就可以获取到每个方法的执行时间了,但是这样操作存在的问题也是显而易见的,当然我相信你肯定也发现了,主要总结为以下几点:

那么针对这种方式的劣势,如何才能更加优雅的实现获取方法的耗时呢?答案就是采用AOP的方式来实现。AOP 方案的实现,有兴趣请自行了解
谈谈Android AOP技术方案
Android AOP — AspectJ的使用

五、App启动速度优化

优化总方针:

1.懒加载:
核心思想:需要用到时才加载。下面列具一些:

2.延迟初始化
核心思想:不阻碍启动过程,找到合适的时机再去加载。
难点:对于合适的加载时机难以把控。

推荐此方案,执行时机明确,执行的时机是在系统空闲的时候进行执行,有效缓解列表卡顿,它可以真正的提升用户的体验,不过需要注意queueIdle方法回调的执行也是会阻塞线程的,如果任务耗时比较长,可以选择建立任务队列,一个一个任务地执行。任务队列过长,可能会导致任务不执行或者执行时间过长,因为queueIdle的回调是MessageQueue 的 next()第一次轮训时,message 为空才执行一次。详细请看 MessageQueue 空闲任务 IdleHandler 机制

/*** 延迟初始化分发器 */
public class DelayInitDispatcher {

    private Queue<Runnable> mDelayTasks = new LinkedList<>();

    private MessageQueue.IdleHandler mIdleHandler = new MessageQueue.IdleHandler() {
        @Override
        public boolean queueIdle() {
            if (mDelayTasks.size() > 0) {
                mDelayTasks.poll().run();
            }
            return !mDelayTasks.isEmpty();
        }
    };

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

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

}

3.异步加载
核心思想:子线程分担主线程任务,并行减少时间。
难点:说到子线程,那大家想到的肯定是线程池了,但是如果任务间存在依赖关系,我们就无法简单地直接把任务添加到线程池就能完成。即使你把有依赖关系的任务,合并到同一个任务去,在可读性上也比较差。所以有以下方案的推荐:

阿里开源的一个启动器库alpha:https://github.com/alibaba/alpha

启动器介绍:
核心思想:充分利用CPU多核,自动梳理任务顺序

启动器流程:

4.优化体验实现预加载

方案:
主要是从交互设计上来优化,例如刚启动app时,可以设置 SplashActivity,可以设置欢迎页、展示App logo。进入SplashActivity,大约经过1~2秒再跳转到程序的主界面。并且我们在可以在SplashActivity 的 onWindowFocusChange()方法回调后做一些其他初始化工作,达到预加载的效果。目前很多App都是这么做的。当然也可以直接在拉起MainActivity后先展示logo 、欢迎页等,等待1-2秒再展示真正的界面,并在onWindowFocusChange()方法回调后做一些其他初始化工作,达到预加载的效果。

https://blog.csdn.net/yywan1314520/article/details/51622154

5.技术优化

一些启动优化黑科技简单介绍,上网搜索相关字段可以搜索到一些文章,这里没有成熟的方案提供给大家:

参考:
抖音 Android 性能优化系列:启动优化实践
性能优化总结-Android启动速度优化
Android启动优化你真的了解吗?
深入探索Android启动速度优化(上)
深入探索Android启动速度优化(下)

上一篇下一篇

猜你喜欢

热点阅读