Android性能优化 — — 启动篇2:Activity的创建

作为开发者,我们可以开发出令用户高兴和喜欢的界面,但不幸的是,为了这很棒的体验,用户不得不等待一些时间,耗上一点内存去初始化完所有的子系统,资源,和布局。

我是Colt McAnlis,重要的一点是你是可以通过提升界面的加载性能来提升整体应用的健康和性能。

用户启动应用,在应用正在加载准备显示之前,会显示开始窗口。

(链接:Startup time 101

(链接:Android性能优化 — — 启动篇1:Understanding App Launch Time了解应用启动

大多数情况下,用户在启动页等待时间过长,问题最有可能在你主要界面的初始化上。我是说,这里有很多工作要做:设置主题数据,填充view,加载图片,序列化网络读取的内容,写用户的配置等等,所有为了绘制界面的工作 。

如果你不关注这里,这里面的每一个小的操作都可能陷入性能陷阱,比如多次的GC事件或者等待填充布局或者网络请求的阻塞,所有事情都会耽搁用户看到界面的时间。

诊断问题

想要界面的加载更简单给用户提供最好的体验。这里有些你需要做的:第一,你可以通过Method Tracer工具来帮你查找哪里出了问题。(链接: Android Studio Method Tracer)通过在代码中嵌入trace命令,它会以快照的形式形象的告诉你哪些地方是耗时的,比如调用栈,方法等。如果界面的onCreate()耗时长达16到30毫秒,那么它就是值得我们去深究为什么耗时这么长。

当你做的时候,开始的时候和结束的时候之间测试时间将会记录下来,然后在你的Systrace捕获窗口上显示,你会看到更多有关耗时地方的信息。(链接: Android Studio Systrace)

普遍问题

如果觉得应用的加载时间过长,可以使用tracer代码来发现问题。但是条件不允许的话,可以试试下面的方法来解决问题。

第一个最普遍的问题就是因为填充界面布局导致的界面加载慢。我们可以看到这样的布局有很多层级,需要更多的时间去填充,也需要加载更多的图片和资源,导致增加加载时间。同样的,你可以做一些事情来扁平化层级,减少复杂性,或者砍掉那些不能显示的部分,这些事情马上就会帮你界面减少创建的时间。

第二个问题是,试着去重构你的代码,尽可能的依靠延迟加载和异步线程。通常来说,在onCreate()中对上述所有的东西进行初始化会造成界面的卡顿。这些事情中的一些需要在onCreate()中去做,比如初始化布局中的view对象,而另外的一些可以延迟到后面,比如当真正需要显示图片的时候,我们再去采用异步的方式加载并初始化它。

在创建界面的时候采用延迟加载,会让界面的性能更好些。

附:英文字幕

As developers, there’s nothing we like more than an amazing activity that delights and entertains our users.But sadly, initializing all the subsystems, resources, and layouts to provide that experience takes a bit of time and memory, meaning the users are going to have to wait for their transcendent experience.

My name is Colt McAnlis, and one of most important things that you can do for the health and performance perception of your application is optimizing the performance of loading your activities.

Remember, when the user launches your app, they’ll be shown a start window while your app is loading and getting ready to display.(Link:Startup time 101)

Now, most of the time, if your user is spending too much time starting at the screen, the problem is most likely to be in the creation of your main activity. I mean, a bunch of stuff happens here. You’re setting the theme data, inflating view hierarchy, loading bitmaps, deserializing network fetches, writing user preferences- you know, all the stuff you need to display your activity.

But if you’re not careful, each of these little operations can fall into their own performance pitfalls-things like multiple garbage collection events or waiting to inflate views or blocking on network requests- all things which can delay the time it takes for the first pixel to be shown to the user.

Diagnosing the problem

So if you’d like to streamline your activity loading to give users the best experience possible, here’s what you need to do. First, figure out if you actually have a problem, which you can do with the method tracing tool.(Link: Android Studio Method Tracer)This will give you a snapshot of your call stack and let you visually see what functions are taking longer than others. If the onCreate function of your activity is taking longer than 16 to 30 milliseconds, then it’s worth exploring more to see what might be causing the delay. And this can be done by inserting trace commands at various parts of your code.

When you do this, the timing between the begin section and end sections will be logged and then displayed in your Systrace captures so that you can see more information about where your time is going.(Link: Android Studio Systrace)

Common problems

Now,if you’ve found that your load time is taking too long, hopefully you’ve been able to narrow it down using the inline tracing code. If not, here’s a couple of common problems and how to address them.

Firstly, the most common problem we see with slow activity loads has to be the time it takes to inflate a view hierarchy. See, the larger your hierarchy, the more time it’s taken to inflate it, and the more bitmaps or resources it requires to load also adds to its load time. As such, anything you can do to flatten the hierarchy, reduce complexity, or stub out portions that aren’t visible right now will help to reduce the time spent doing this work at the creation time of your activity.

Secondly, try to structure your code to rely on lazy loading and async processing as much as possible.Commonly, the onCreate method of your activity becomes a junk drawer for all sorts of different initialization routines. Some of those things do need to happen right now. Others can be delayed until later. This includes things like doing initial minimal loading of your hierarchy, loading all of your initial images in an async fashion, and waiting to initialize heavy systems until they are absolutely needed.