5 种 提高 Xamarin.Forms App 启动时间的 方法

适用于 iOSAndroidXamarin SDK 提供了一个非常高性能的基础,以便构建 Xamarin.Forms 跨平台应用程序。当你努力优化 Xamarin.Forms 应用程序的启动速度和响应速度时,请记住,能优化构建在 Xamarin SDK 基础之上的iOSAndroid应用的方法 也能优化 Xamarin 跨平台的应用程序。而且这些优化从最开始的启动就起作用。

PS: 即适用于原生 AndroidiOS 的性能优化方法也适用于 Xamarin.iOSXamarin.Android

启动时间的定义

首先,让我们将 启动 定义为从用户点击应用图标到第一个界面可见时发生的所有事情。当你对比一个 新建的Xamarin.Android 和 新建的 Xamarin.Forms 项目的时候,你会发现 Xamarin.Android 项目加载的更快一些。这中间发生了什么呢?

Xamarin.Forms 不仅提供跨平台共享的 UI, 还提供了一些常见的应用功能比如: AppLinks for deep linking, Navigation, MessagingCenter, and DependencyService, 还有一些必要的跨平台的 UI: alerts, action sheets, toolbars, status bars, etc.

如果你向 Xamarin.Android 应用程序添加类似的实现时, 你就会看到之前 Xamarin.AndroidXamarin.Forms 性能上的差异相差无几了。这就解释了为什么 Xamarin.Forms app 为什么启动时间会稍长一点,那我们如何来控制 Xamarin.Forms app 的启动时长呢? 以下是我在 iOSAndroidUWP targets 中优化 启动时间 的五个建议。

1. 优先加载本地资源

我们通常希望在 应用程序启动后 立即加载最新的数据, 但这会减慢 first screen appearingpopulating 的速度(类似:Android Actvity --> OnCreate() and OnResume()). Use state from a previous run or have content ready to go that is for the first run.

We often want to load fresh data as soon as our application has launched, but this will only slow down the first screen from appearing and populating. Use state from a previous run or have content ready to go that is for the first run.

如果你的 app 可以离线使用的话,我们很推荐这样做。优先加载本地资源,之后立即为你的第一个屏幕填充内容了。Azure Mobile Apps and Realm with Azure 是很好的选择。

当你必须 访问网络 以获取首次运行内容时,你可以提供一些 UI,比如通过使用 加载指示器 (loading indicator)告诉用户 你的 app 正在做什么。这样一来还可以避免白屏的尴尬:先展示占位符,告诉用户屏幕已经加载出来,现在要去加载数据。

Payload Tips:将你的网络的需求降到最低,不要花时间处理一些耗时的操作,比如解析字符串,而是在需要表示数据时提供数据。

2. 优化 Assets

图像和视频通常会比较大,可能会大幅减慢屏幕的初始渲染速度。减少对 Assets 的依赖,并优化您用于必要 dimensions 的任何 media 文件。不要指望 Android OS 为您调整 Assets 大小。

对于 Android target screensAssets 放置在表示其 density 的文件夹中:

  • ldpi (low) ~120dpi
  • mdpi (medium) ~160dpi
  • hdpi (high) ~240dpi
  • xhdpi (extra-high) ~320dpi
  • xxhdpi (extra-extra-high) ~480dpi
  • xxxhdpi (extra-extra-extra-high) ~640dpi

还有一个特殊的 nodpi 密度,告诉 Android 无论屏幕密度如何都不会 scale the resources 。

当您将较大的 image 放在 ldpi 文件夹中并在 xxhdpi 的屏幕上加载该资源时,Android 会对其进行扩展。
这很慢并且会使增加运行时内存的消耗,有时甚至会导致应用程序崩溃;

要管理那么多的 assetsassets 资源,非常建议使用像 SketchZeplin 一样的应用来生成适用于多种尺寸屏幕的 资源文件。

Xamarin.Android 7.0 中还出了个实验性的选项 pre-crunch PNG 文件:AndroidExplicitCrunch.

这进一步减少了 Assets(和应用程序)的大小,减少了 build time 并对运行时的运行速度也有一定的优化。想要使用这个功能,需要编辑你的 Android csproj 文件,并修改 build configuration 中的 PropertyGroup.

<PropertyGroup>
    ...
    <AndroidExplicitCrunch>true</AndroidExplicitCrunch>
</PropertyGroup>

3. 懒加载你不需要的东西 来进行优化

App.xaml Resources 可以放置 styles, fonts 或者其它一些你需要在你的 app 中使用的 资源,但这些都是在启动时加载的。所以如果你想 毫秒 级别的减少你的 app 启动时间的话, 那你就去掉 App.xaml 中的这些代码,lazy load it by page or in another method.

4. Enable XAML Compilation

XAML 是一种流行且功能强大的声明用户界面的方式。如果你选择使用 C# 并用 XAML 来构建 UI 的话....

XAML is a popular and expressively powerful way to declare your user interface. If you opt to stay in C# and build your UI there, it’s naturally compiled along with the rest of your code, giving you compile-time checking and speed. When you want that same benefit while using XAML, you enable XAML Compilation (XAMLC). This will compile your XAML into Intermediate Language (IL) and add it to your compiled assembly, resulting in faster startup and runtime performance.

我们来看看如何启用它:

application 级别,您可以声明您的 XAMLC 选项,它将影响您的整个应用程序:

using Xamarin.Forms.Xaml;
...
[assembly: XamlCompilation (XamlCompilationOptions.Compile)]
namespace PhotoApp
{
    ...
}

如果要在 class 级别设置 XAMLC 选项,则可以:

using Xamarin.Forms.Xaml;
...
[XamlCompilation (XamlCompilationOptions.Compile)]
public class HomePage : ContentPage
{
    ...
}

启用 XAMLC 后,您将获得大多数所有属性的编译时 XAML 检查,UI 将更快地呈现。当您在程序集中交换 IL.xaml 文件大小时,文件大小可能保持不变或略有增长。

When XAMLC is enabled you’ll get compile time XAML checking on most all properties and UI will render faster. File size may remain unchanged or grow slightly as you are trading .xaml file size for IL in the assembly.

5. 减少 Assemblies 的数量

通常情况下便利总是要付出成本的。这可能是一个非常小的成本,但你想全力优化性能时就另说了。通过 NuGet 来引用第三方库虽然简单好用,但实际情况是,当调用跨越 boundaries时,移动应用程序所依赖的组件越多(越大)自然会降低执行速度。

Convenience comes at a cost, as usual. It might be a very small cost, but you want to leave no stone unturned when tuning for performance. While NuGet packages are awesome for leveraging other libraries, the reality is that the more (and larger) assemblies your mobile application depends on naturally slows down the execution as calls pass across boundaries.

Xamarin.Forms, for example, inspects all assemblies for [ExportRenderer] attributes and currently has no method to opt-in or opt-out. This is something we’re working to improve.

权衡每个依赖的优缺点,并在可能的情况下将该代码放入你的主应用程序中。这有可能会让你的工作量变大一些,所以你权衡一下吧。这是经常被忽略的一点,但也是可以用来优化 app 性能的一点。

彩蛋 1:预编译 AOT -- Ahead of Time Compilation

之所以叫它彩蛋是因为我们目前还是把 Android 中的 AOT 当作 experimental 的功能来看,而且这不是对所有人都适用。 当然,iOS 里默认使用 AOTLLVM 编译,所以在这也没什么好说的。

Enable the experimental Android AOT and get immediate improvement in startup as well as overall speed by reducing some Just-In-Time compilation overhead. The price paid is an increase in the size of your APK, so you should try this out and weigh the pros and cons for your application. To enable AOT, open your project configuration and check the box.

VS for Mac 中 开启这个选项:

Android_Build_Settings_General_Callout.png

注意: AOT is available on Xamarin Android 5.1 and 7.0+

彩蛋 2:优化 编译时间 | Build Time Improvements

Xamarin 项目通常比原生的项目会花费更多的 build time, 如何来优化呢?可以参考:关于如何加快编译 Xamarin 应用程序所需时间的提示和技巧

While not directly applicable to startup improvement, one of our awesome mobile solutions architects Brandon Minnick has shared his collection of build optimization configurations. Check it out on GitHub.

之后怎么优化?

以上只是我比较喜欢的几个建议,而且它们不仅可以优化 app 启动时间。 我可以继续关于 扁平化布局,优化布局周期中的 measuringlayout 等来继续深入优化。你可以在 Xamarin.Forms Performance guide 里看到这些内容。

社区 和 Xamarin.Forms 工程师团队一直在 Xamarin Forums (论坛) 讨论一些 Xamarin 的痛点和相应的解决方案。 欢迎大家来加入一起讨论下如何继续优化 Xamarin 的性能。

Link: https://blog.xamarin.com/5-ways-boost-xamarin-forms-app-startup-time/

推荐阅读更多精彩内容