盒子
盒子
文章目录
  1. 介绍
  2. 原理
  3. 手动埋点
  4. AOP切面编程
  5. Factory
  6. 开发工具
  7. 优化技巧
  8. 结语
  9. 推荐

Android布局耗时监测的三种方式,你的选择将决定你的高度

在Android应用开发中,性能优化是一个至关重要的方面。其中,布局渲染的性能直接影响用户体验,特别是在一些复杂页面中,布局渲染的耗时可能会导致界面卡顿,影响用户体验。因此,为了更好地监测布局渲染的耗时,我们需要一种可靠的实现方案。本文将介绍三种针对Android布局耗时监测的实现方案,帮助开发者及时发现并解决布局性能问题。

介绍

布局渲染的耗时是指从布局文件加载到界面显示完成所花费的时间。通常,我们使用开发者选项中的布局边界线来查看布局渲染的性能情况,但是这种方法并不能准确地反映布局渲染的耗时。因此,我们需要一种更精确的监测方案来定位布局性能问题。

原理

布局耗时监测的原理就是在布局过程中的关键节点插入计时代码,记录每个阶段的耗时,从而分析出布局耗时的瓶颈所在。

手动埋点

最简单的布局耗时监测方案就是在布局过程中的关键节点手动插入计时代码,例如:

1
2
3
4
5
6
7
8
9
10
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

long startTime = System.currentTimeMillis();
// 解析 XML 布局文件
setContentView(R.layout.activity_main);
long endTime = System.currentTimeMillis();
long cost = endTime - startTime;
Log.d("TAG", "布局耗时:" + cost + "ms");
}

这种方案的缺点是需要手动插入代码,比较繁琐,而且不够灵活。

AOP切面编程

使用AOP切面编程可以更加优雅地实现布局耗时监测。例如,使用AspectJ框架可以定义一个切面,在setContentView()方法执行前后分别插入计时代码:

1
2
3
4
5
6
7
8
9
10
11
12
@Aspect
public class LayoutTimeAspect {

@Around("call(* android.app.Activity.setContentView(..))")
public void aroundSetContentView(ProceedingJoinPoint joinPoint) throws Throwable {
long startTime = System.currentTimeMillis();
joinPoint.proceed();
long endTime = System.currentTimeMillis();
long cost = endTime - startTime;
Log.d("TAG", "布局耗时:" + cost + "ms");
}
}

这种方案的优点是代码更加简洁优雅,而且可以扩展到其他需要监测耗时的操作。

类似的还有通过ASM的方法进行插桩,本质都是一样,在特定的方法时机中插入对应的监测代码。

Factory

如果我们要知道特定的某个view的耗时,这个时候就可以使用LayoutInflaterCompat.Factory2

该方法用于设置一个LayoutInflater.Factory2对象,用于替换LayoutInflater在解析XML布局文件时创建View的行为。通过自定义 LayoutInflater.Factory2,我们可以拦截和修改布局的加载过程,包括创建View和设置属性等。

简单的理解,就是它能拦截view的创建过程,所以我们可以通过这个特性来监听布局中每一个view的具体耗时。

下面是一个简单的示例:

1
2
3
4
5
6
7
8
9
10
11
12
class MyFactory2 : LayoutInflater.Factory2 {

override fun onCreateView(parent: View?, name: String, context: Context, attrs: AttributeSet): View? {
val startTime = System.nanoTime()
val view = LayoutInflater.from(context).createView(name, attrs)
val endTime = System.nanoTime()
val costTime = endTime - startTime
Log.d("TAG", "View $name layout cost time: $costTime")
return view
}
...
}

这种方案的有点是能够更加具体化,可以帮助监测到具体的view。

开发工具

除了线上的监测功能,线下的分析也至关重要。Android提供了一些相关分析工具,能够很好的帮助开发者分析各种性能。

例如,Systrace是Android开发者工具中的一部分,它可以用来分析应用程序在Android系统上的性能问题,包括布局、绘制、CPU、内存等方面的性能问题。

所以针对布局耗时,我们也可以使用Systrace来进行线下分析。

1
2
TraceCompat.beginSection("start");
TraceCompat.endSection();

在需要检测的地方做标记,然后再进行收集数据

1
$ python systrace.py --time=10 -o my_trace.html sched gfx view

这条命令会在10秒内收集与调度、图形渲染、视图布局相关的性能数据,并将数据保存到名为 my_trace.html 的文件中。

生成完之后,我们只需要打开得到的html,可以直接在浏览器中打开。报告文件中包含了各种性能指标的图表和分析,可以通过查看相关的部分来了解布局的耗时情况。

1710229845178.jpg
除此之外还有,TraceViewLayoutInspector等工具都能有效的辅助分析布局的耗时。

优化技巧

在监测并发现到布局问题的时候,剩下的就是解决布局耗时问题。下面提供一些优化布局耗时的方案。

  • 注意避免在布局渲染过程中进行耗时操作,以免影响性能。
  • 使用合适的布局管理器和布局优化技巧,减少布局层次和复杂度,提高布局渲染效率。
  • 对于一些复杂布局,可以考虑使用异步加载布局来减少布局加载时间。

结语

通过以上实现方案,我们可以准确监测Android应用中布局渲染的耗时,及时发现并解决布局性能问题,从而提升用户体验。希望本文能帮助到Android开发者更好地优化应用性能。

推荐

android_startup: 提供一种在应用启动时能够更加简单、高效的方式来初始化组件,优化启动速度。不仅支持Jetpack App Startup的全部功能,还提供额外的同步与异步等待、线程控制与多进程支持等功能。

AwesomeGithub: 基于Github的客户端,纯练习项目,支持组件化开发,支持账户密码与认证登陆。使用Kotlin语言进行开发,项目架构是基于JetPack\&DataBinding的MVVM;项目中使用了Arouter、Retrofit、Coroutine、Glide、Dagger与Hilt等流行开源技术。

flutter_github: 基于Flutter的跨平台版本Github客户端,与AwesomeGithub相对应。

android-api-analysis: 结合详细的Demo来全面解析Android相关的知识点, 帮助读者能够更快的掌握与理解所阐述的要点。

daily_algorithm: 每日一算法,由浅入深,欢迎加入一起共勉。

支持一下
赞赏是一门艺术