文章目录
android 性能优化之启动优化
启动状态
冷启动
冷启动是应用程序启动的默认方式。当用户首次启动应用程序时,或者系统彻底杀死了应用程序进程后再次启动应用程序时,会经历冷启动。在冷启动过程中,系统需要创建一个新的进程,并初始化所有必要的资源。这包括加载应用程序的代码、数据,以及初始化应用程序的环境。冷启动的时间相对较长,因为系统需要执行一系列初始化操作。用户能感受到明显的等待时间,这段时间从点击应用图标到看到应用程序主界面出现。
在冷启动开始时,系统有以下三项任务:
- 加载并启动应用。
- 在启动后立即显示应用的空白启动窗口。
- 创建应用进程。
系统一创建应用进程,应用进程就负责后续阶段:
- 创建应用对象。
- 启动主线程。
- 创建主 activity。
- 膨胀视图。
- 创建屏幕布局。
- 执行初步绘制。
温启动
温启动是指应用程序已经在后台运行,但由于系统资源紧张等原因被系统终止。当用户再次启动应用程序时,系统会重新加载应用程序。与冷启动相比,温启动不需要重新创建进程,因此启动时间较短。
热启动
热启动是指应用程序处于前台运行状态,用户通过返回键或应用程序内部的逻辑退到后台,然后又重新显示到前台。在这种情况下,应用程序的进程仍然在运行,所以不需要进行任何初始化操作。热启动是最快的启动方式,因为系统只需要恢复应用程序的前台状态。
耗时检测
检测手段
- 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
发表评论