当前位置: 代码网 > it编程>App开发>Android > Android 性能优化之启动优化

Android 性能优化之启动优化

2024年08月02日 Android 我要评论
启动状态:冷启动、温启动、热启动。耗时检测:TraceView、Systrace、AOP。优化手段:白屏优化、异步加载优化、延迟加载优化、AppStarup。

android 性能优化之启动优化

启动状态

在这里插入图片描述

冷启动

冷启动是应用程序启动的默认方式。当用户首次启动应用程序时,或者系统彻底杀死了应用程序进程后再次启动应用程序时,会经历冷启动。在冷启动过程中,系统需要创建一个新的进程,并初始化所有必要的资源。这包括加载应用程序的代码、数据,以及初始化应用程序的环境。冷启动的时间相对较长,因为系统需要执行一系列初始化操作。用户能感受到明显的等待时间,这段时间从点击应用图标到看到应用程序主界面出现。

在冷启动开始时,系统有以下三项任务:

  1. 加载并启动应用。
  2. 在启动后立即显示应用的空白启动窗口。
  3. 创建应用进程

系统一创建应用进程,应用进程就负责后续阶段:

  1. 创建应用对象。
  2. 启动主线程。
  3. 创建主 activity。
  4. 膨胀视图。
  5. 创建屏幕布局。
  6. 执行初步绘制。

在这里插入图片描述

温启动

温启动是指应用程序已经在后台运行,但由于系统资源紧张等原因被系统终止。当用户再次启动应用程序时,系统会重新加载应用程序。与冷启动相比,温启动不需要重新创建进程,因此启动时间较短。

热启动

热启动是指应用程序处于前台运行状态,用户通过返回键或应用程序内部的逻辑退到后台,然后又重新显示到前台。在这种情况下,应用程序的进程仍然在运行,所以不需要进行任何初始化操作。热启动是最快的启动方式,因为系统只需要恢复应用程序的前台状态。

耗时检测

检测手段

  • traceview
  • systrace
  • aop统计耗时

traceview

traceview 是 android sdk 中提供的性能分析工具,它可以帮助开发者分析应用程序的方法调用和线程活动。traceview 专注于应用程序的内部行为,提供了方法执行时间、调用次数、cpu 使用率等详细信息。它通常用于分析应用程序的特定部分或特定场景。

使用方式
public class baseapp extends application {  
    @override
    public void oncreate() {
        super.oncreate();
        // traceview开始
        debug.startmethodtracing("mytrace001");
        initrefresh();
        inittitlebar();
        inittoast();
        initactivites();
        // traceview结束
        debug.stopmethodtracing();
    }
}

运行程序后生成文件:/sdcard/android/data/com.example.android_performance_optimization/files/mytrace001.trace

在这里插入图片描述

将 trace 文件到处,用 androidstudio的 profiler 工具打开,可以清楚看到各个方法的执行时间:

在这里插入图片描述

缺点
  • 运行时开销严重,整体会变慢。
  • 可能带偏优化方向。

systrace

systrace 是 android sdk 中提供的另一个性能分析工具,它提供了系统级别的跟踪信息,包括内核调度、硬件i/o、进程/线程调度等。systrace 专注于整个 android 系统的行为,帮助开发者了解系统资源的使用情况和潜在的瓶颈。

环境配置

https://blog.csdn.net/donald_zhuang/article/details/118771191

https://blog.csdn.net/jdsjlzx/article/details/134179374

使用方式
public class baseapp extends application {
    @override
    public void oncreate() {
        super.oncreate();
        // systrace开始
        trace.beginsection("mytrace002");
        initrefresh();
        inittitlebar();
        inittoast();
        initactivites();
        // systrace结束
        trace.endsection();
    }
}

先执行命令:python d:\dev\androidsdk\platform-tools\systrace\systrace.py -t 10 -o mytrace.html -a com.example.android_performance_optimization sched freq idle am wm gfx view binder_driver hal dalvik camera input res

然后运行程序,大概10秒后会生成 mytrace.html 文件。

打开 html 文件过滤相关信息后可以看到 wall duration 耗时:

在这里插入图片描述

traceview和systrace比较

性能消耗

  • traceview:由于它收集所有方法的耗时信息和嵌套关系,因此本身的性能消耗很大,可能会影响到实际的运行环境,统计的耗时可能不准确。
  • systrace:采用了不同的思路,通过有限的label先粗略统计出一个阶段的耗时,定位到问题后再进一步细化和测算分析。这种方式相对于traceview来说,对性能的影响较小。

适用范围

  • traceview:更适用于从软件跟踪的角度分析应用程序的性能。
  • systrace:则更侧重于从系统整体的角度分析android系统的性能,包括各个关键子系统和服务的运行情况。

aop统计耗时

环境配置

这里使用第三方框架:https://github.com/flyjingfish/androidaop

添加依赖库:

implementation 'io.github.flyjingfish.androidaop:android-aop-core:1.8.8'
implementation 'io.github.flyjingfish.androidaop:android-aop-annotation:1.8.8'
annotationprocessor 'io.github.flyjingfish.androidaop:android-aop-processor:1.8.8'
使用

定义注解:

@androidaoppointcut(costtimepointcut.class)
@retention(retentionpolicy.runtime)
@target(elementtype.method)
public @interface costtime {
}

定义切面类:

public class costtimepointcut implements basepointcut<costtime> {
    @nullable
    @override
    public object invoke(@nonnull proceedjoinpoint proceedjoinpoint, @nonnull costtime costtime) {
        long starttime = system.currenttimemillis();
        proceedjoinpoint.proceed(); // 继续执行原方法
        long time = system.currenttimemillis() - starttime;
        class<?> targetclass = proceedjoinpoint.gettargetclass();
        string classname = targetclass.getname();
        aopmethod targetmethod = proceedjoinpoint.gettargetmethod();
        string methodname = targetmethod.getname();
        string builder = classname + "#" + methodname + " [" + time + "ms" + "] ";
        log.e("costtime", builder);
        return null;
    }
}

使用aop:

public class baseapp extends application {

    @costtime
    @override
    public void oncreate() {
        super.oncreate(); 
        initrefresh(); 
        inittitlebar(); 
        inittoast(); 
        initactivites(); 
    }

    @costtime
    private void initactivites() {
        activitymanager.getinstance().init(instance);
    }

    @costtime
    private void inittoast() {
        toastutils.init(instance, new toaststyle());
        toastutils.setdebugmode(appconfig.isdebug());
        toastutils.setinterceptor(new toastloginterceptor());
    }

    @costtime
    private void inittitlebar() {
        titlebar.setdefaultstyle(new titlebarstyle());
    }

    @costtime
    private void initrefresh() {
        smartrefreshlayout.setdefaultrefreshheadercreator(new defaultrefreshheadercreator() {
            @override
            public refreshheader createrefreshheader(context context, refreshlayout layout) {
                layout.setprimarycolorsid(r.color.black, android.r.color.white);//全局设置主题颜色
                return new classicsheader(context);
            }
        });
        smartrefreshlayout.setdefaultrefreshfootercreator(new defaultrefreshfootercreator() {
            @override
            public refreshfooter createrefreshfooter(context context, refreshlayout layout) {
                return new classicsfooter(context).setdrawablesize(20);
            }
        });
    }
}

输出:

com.example.android_performance_optimization.baseapp#initrefresh [1ms] 
com.example.android_performance_optimization.baseapp#inittitlebar [0ms] 
com.example.android_performance_optimization.baseapp#inittoast [0ms] 
com.example.android_performance_optimization.baseapp#initactivites [1ms] 
com.example.android_performance_optimization.baseapp#oncreate [2ms] 

优化

  • 白屏优化
  • 异步加载优化
  • 延迟加载优化

白屏优化

在启动时提供一个简洁的初始界面给用户,增强用户体验。

定义主题:

<style name="splashtheme" parent="apptheme">
    <!--        设置背景图-->
    <item name="android:windowbackground">@drawable/shape_splash</item>
    <!--        取消标题栏-->
    <item name="windownotitle">true</item>
    <item name="windowactionbar">false</item>
    <!--        设置window不透明-->
    <item name="android:windowistranslucent">false</item>
    <!--        禁用窗口的预览动画-->
    <item name="android:windowdisablepreview">true</item>
    <!--        取消遮盖-->
    <item name="android:windowcontentoverlay">@null</item>
    <!--        全屏-->
    <item name="android:windowfullscreen">true</item>
</style>

配置androidmanifest.xml:

<activity
    android:name=".splashactivity"
    android:exported="true"
    android:launchmode="singletop"
    android:theme="@style/splashtheme">
    <intent-filter>
        <action android:name="android.intent.action.main" />
        <category android:name="android.intent.category.launcher" />
    </intent-filter>
</activity>

异步加载优化

环境配置

这里使用第三方框架:https://github.com/aiceking/appstartfaster

添加依赖库:

implementation 'com.github.aiceking:appstartfaster:2.2.0'
使用
public class baseapp extends application {
    private static baseapp instance;

    public static baseapp getinstance() {
        return instance;
    }

    @costtime
    @override
    public void oncreate() {
        super.oncreate();
        instance = this; 
        appstarttaskdispatcher.create()
            .setshowlog(true)
            .addappstarttask(new activitytask(instance))
            .addappstarttask(new toasttask(instance))
            .addappstarttask(new titlebartask())
            .addappstarttask(new refreshtask())
            .start()
            .await();
    }
}

延迟加载优化

idlehandler 是一个用于在主线程(ui 线程)空闲时执行任务的接口。

使用场景:

  • 数据预加载。
  • 清理资源。
  • 日志上传。
  • 检查更新。
  • 性能分析。

使用:

首先,你需要创建一个实现了idlehandler接口的类或使用匿名内部类。在queueidle()方法中定义你希望在空闲时执行的代码逻辑。该方法的返回值决定了idlehandler的生命周期:

  • 返回true表示idlehandler将继续保留在集合中,下次消息队列空闲时还会再次调用queueidle()
  • 返回false表示执行完毕后将从集合中移除,不再重复调用。

定义延迟加载启动器:

public class delayinitdispatcher {
    private delayinitdispatcher() {
    }

    public static delayinitdispatcher newinstance() {
        return new delayinitdispatcher();
    }

    private linkedlist<task> mdelaytasks = new linkedlist<>();

    private messagequeue.idlehandler midlehandler = new messagequeue.idlehandler() {
        @override
        public boolean queueidle() {
            if (mdelaytasks.size() > 0) {
                task task = mdelaytasks.poll();
                task.run();
            }
            return !mdelaytasks.isempty();
        }
    };

    public delayinitdispatcher addtask(task task) {
        mdelaytasks.add(task);
        return this;
    }

    public void start() {
        looper.myqueue().addidlehandler(midlehandler);
    }
}

定义task接口:

public interface task extends runnable{
}

定义2个任务:

public class preloadtask implements task {
    @override
    public void run() {
        try {
            thread.sleep(1000l);
            log.e("tag", "预加载数据");
        } catch (interruptedexception e) {
            throw new runtimeexception(e);
        }
    }
}
public class cleartask implements task {
    @override
    public void run() {
        try {
            thread.sleep(2000l);
            log.e("tag", "清理资源");
        } catch (interruptedexception e) {
            throw new runtimeexception(e);
        }
    }
}

使用:

delayinitdispatcher.newinstance()
        .addtask(new preloadtask())
        .addtask(new cleartask())
        .start();

appstartup

  • appstartup 是一个可以用于加速app启动速度的 jetpack 组件。
  • appstartup 是借助 contentprovider 进行提前初始化操作

https://blog.csdn.net/qq_14876133/article/details/119247723

源码下载

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com