The Android Developer Challenge is back! Submit your idea before December 2.

优化表盘

Wear OS 表盘会持续不断地运行,所以必须高效地使用电能。

另外,表盘的性能也应当优化。服务不得执行不必要的计算。带有动画的表盘在适应通知和系统指示器的同时必须顺畅地运行。

基本优化

此部分包含提升效率的最佳做法。

表盘的颜色和亮度

深色背景可以节省手表的电量。以下是有关如何设置表盘背景以优化表盘电池使用情况的建议:

  • 颜色。尽可能使用黑色背景。
  • 亮度。如果表盘要求不允许使用黑色背景,您应该力求使背景颜色的亮度在 HSV(色相、饱和度、明度)或 HSB 刻度上不超过 25%。例如,如果您使用 Color 类设置背景颜色,并通过 HSV 刻度定义颜色,则应该将“明度”(即亮度设置)设为 25 或更小的数字。

在 WatchFaceService.Engine 中使用回调

确保表盘仅在处于活动状态时执行计算;请在 WatchFaceService.Engine 中使用回调。最好使用该类的下列方法来确定表盘是否可见:

  • onVisibilityChanged(boolean)
  • isVisible()

或者,使用该类 (WatchFaceService.Engine) 的以下方法:

  • onCreate()
  • onDestroy()

使用通过 DataClient 接口注册的监听器

要监听事件,请使用通过 DataClient.addListener 注册的实时监听器。要查看示例,请参阅同步数据项

请勿使用 WearableListenerService 监听事件,因为无论表盘是否处于活动状态都会调用它。如需了解详情,请参阅弃用 BIND_LISTENER

请勿在 Android 清单文件中注册广播接收器来获取系统事件(如时区变化、电池事件,等等),因为无论表盘是否处于活动状态都会调用 BroadcastReceiver。不过,您可以使用 Context 类的 registerReceiver 方法来注册接收器。

借助动态功能与手机进行交互

当表盘需要在手机上运行某项操作时,只能在表盘处于活动状态时执行相应代码。建议利用 CapabilityClient API 使手机上的应用确定对应的表盘是否处于活动状态。

定义一项在 WatchFaceService.EngineonCreate() 方法中动态添加的功能。您可以通过 onDestroy() 方法移除该功能。

例如,如果某个应用获取要在表盘上显示的周期性数据,那么它应该针对表盘所广播的功能注册监听器。您可以添加提醒,用来获取更新后的数据并将其推送到表盘(当手表在覆盖范围内时)。如果表盘不再处于选中状态、不在覆盖范围内、已关闭或无法接收更新,则移除周期性提醒。

监控耗电量

Wear OS 配套应用让开发者和用户能够查看穿戴式设备上不同进程消耗的电量(在设置 > 手表电池下)。

Android 5.0 中引入了一些有助于延长电池续航时间的功能,如需了解与这些功能相关的信息,请参阅 Volta 项目

注册加密感知表盘

Android 7.0 及更高版本支持文件级加密,并允许加密感知应用在用户(在启动时)提供解密密码之前运行。这可以将从启动动画到表盘的过渡时间缩短多达 30 秒。

要使启动速度更快,请将 android:directBootAware="true" 添加到表盘清单中。

注意:请将此功能与不使用凭据加密存储的表盘结合使用。

动画的最佳做法

本部分介绍的最佳做法有助于减少动画的耗电量。

降低动画的帧速率

动画的计算开销通常很大,且十分耗电。大多数动画在帧速率为每秒 30 帧时看起来已经比较流畅,所以您应避免以更高的帧速率运行动画。如果 draw() 方法的末尾使用了 invalidate(),您可以在调用 invalidate() 方法之前添加延迟以控制帧速率。如需了解如何实现此步骤,请参阅绘制表盘

使 CPU 在各动画之间休眠

动画和对表盘内容的细微更改都会唤醒 CPU。表盘应使 CPU 在各动画之间休眠。例如,您可以在交互模式下使用每秒短时动画,然后使 CPU 休眠到下一秒。使 CPU 经常休眠,即使时间很短,也可以大大减少耗电量。

要最大限度地延长电池续航时间,请谨慎使用动画。即使是闪烁的冒号,每次闪烁都会唤醒 CPU,并影响电池续航时间。

缩减位图资源的大小

许多表盘都包含背景图片及其他图形资源,这些资源会在背景图片上转换和重叠,例如时钟指针和其他设计元素会随着时间的流逝而移动。如绘制表盘中所述,在系统每次重新绘制表盘时,这些图形元素通常会在 Engine.onDraw() 方法内旋转(有时会缩放)。

这些图形资源越大,转换它们所需的计算开销就越大。在 Engine.onDraw() 方法中转换较大的图形资源会大幅降低系统运行动画的帧速率。

图 1. 可以剪裁时钟指针来移除多余像素。

要提升表盘的性能,请执行以下操作:

  • 请不要使用大于实际需求的图形元素。
  • 移除边缘多余的透明像素。

图 1 左侧的示例时钟指针大小可以缩小 97%。

缩减位图资源的大小(如本部分所述)不仅能够提升动画的性能,而且还可以节省电量。

组合位图资源

如果您的某些位图经常一起绘制,不妨考虑将它们组合到同一个图形资源中。您通常可以在交互模式下将背景图片与刻度线组合到一起,以避免系统每次重新绘制表盘时都绘制两个全屏位图。

绘制缩放后的位图时停用抗锯齿

当您使用 Canvas.drawBitmap() 方法在 Canvas 对象上绘制缩放后的位图时,您可以提供 Paint 实例来配置多个选项。要提升性能,请使用 setAntiAlias() 方法停用抗锯齿,因为此选项对位图没有任何影响。

图 2. 停用(左侧)和启用(右侧)位图过滤的示例。

使用位图过滤

对于在其他元素上绘制的位图资源,请使用 setFilterBitmap() 方法在相同的 Paint 实例上启用位图过滤。图 2 显示了应用和未应用位图过滤的时钟指针的放大视图。

注意:在低位微光模式下,系统无法可靠地渲染图片中的颜色,使得位图过滤无法成功地处理位图。当微光模式处于活动状态时,请停用位图过滤。

将开销大的操作移出绘制方法

系统每次重新绘制表盘时都会调用 Engine.onDraw() 方法,所以此方法中应只包含更新表盘所必需的操作,从而提升性能。

如有可能,请避免在 Engine.onDraw() 方法中执行以下操作:

  • 加载图片和其他资源。
  • 调整图像大小。
  • 分配对象。
  • 执行其结果在各个帧之间不会改变的计算任务。

您通常可以在 Engine.onCreate() 方法中执行上述操作。您可以在 Engine.onSurfaceChanged() 方法中提前调整图片大小,此方法会为您提供画布的大小。

要分析表盘的性能,请使用 CPU 分析器。特别是,请确保 Engine.onDraw() 实现的执行时间很短暂,且在不同的调用过程中保持一致。如需了解详情,请参阅记录和检查方法跟踪记录