使用唤醒锁定可能会降低设备性能。如果您需要使用唤醒锁定,请务必正确使用。本文档介绍了一些最佳实践,可帮助您避免常见的唤醒锁定陷阱。
正确命名唤醒锁定
我们建议您在唤醒锁定标签中包含软件包、类或方法名称。这样,如果发生错误,您可以更轻松地在源代码中找到创建唤醒锁定的位置。下面提供了更多相关提示:
- 在名称中省去任何个人身份信息 (PII),例如电子邮件地址。如果设备在唤醒锁定标签中检测到 PII,则会记录
_UNKNOWN,而不是您指定的标签。 - 请勿程序化地(例如通过调用
getName())获取类或方法名称。如果您尝试以编程方式获取名称,则可能会被 Proguard 等工具混淆。您可以改用硬编码字符串。 - 请勿向唤醒锁定标签添加计数器或唯一标识符。每次运行创建唤醒锁定的代码时,都应使用相同的标签。 这种做法可让系统汇总每个方法的唤醒锁定使用情况。
确保您的应用在前台可见
唤醒锁定处于活动状态时,设备会消耗电量。设备的用户应知道这一点。因此,如果您使用的是唤醒锁定,则应向用户显示一些通知。 在实际操作中,这意味着您应在 前台服务中获取和持有唤醒锁定。前台服务必须显示通知。
如果前台服务不是适合您应用的选择,那么您可能也不应使用唤醒锁定。如需了解在应用不在前台时执行工作的其他方法,请参阅 选择合适的 API 以保持设备唤醒状态 文档。
保持逻辑简单
确保获取和释放唤醒锁定的逻辑尽可能简单。当唤醒锁定逻辑与复杂的状态机、超时、执行器池或回调事件关联时,该逻辑中的任何细微错误都可能导致唤醒锁定的保持时间超出预期。这些错误很难诊断和调试。
检查唤醒锁定是否始终释放
如果您使用唤醒锁定,则必须确保正确释放您获取的每个唤醒锁定。这并不总是像听起来那么容易。例如,以下代码存在问题:
Kotlin
@Throws(MyException::class)
fun doSomethingAndRelease() {
wakeLock.apply {
acquire()
doTheWork() // can potentially throw MyException
release() // does not run if an exception is thrown
}
}
Java
void doSomethingAndRelease() throws MyException {
wakeLock.acquire();
doTheWork(); // can potentially throw MyException
wakeLock.release(); // does not run if an exception is thrown
}
这里的问题是,doTheWork() 方法可能会抛出 MyException 异常。如果抛出异常,doSomethingAndRelease() 方法会将异常向外传播,并且永远不会到达 release() 调用。结果是唤醒锁定已获取但未释放,这非常糟糕。
在更正后的代码中,即使抛出异常,doSomethingAndRelease() 也会确保释放唤醒锁定:
Kotlin
@Throws(MyException::class)
fun doSomethingAndRelease() {
wakeLock.apply {
try {
acquire()
doTheWork()
} finally {
release()
}
}
}
Java
void doSomethingAndRelease() throws MyException {
try {
wakeLock.acquire();
doTheWork();
} finally {
wakeLock.release();
}
}