使用 Wake Lock 可能會降低裝置效能。如需使用 Wake Lock,請務必正確操作。本文將介紹一些最佳做法,協助您避免常見的 Wake Lock 陷阱。
正確命名 Wake Lock
建議您在 Wake Lock 標記中加入套件、類別或方法名稱,這樣一來,如果發生錯誤,您就能更輕鬆地在原始碼中找到建立 Wake Lock 的位置。以下提供幾項額外的訣竅:
- 請勿在名稱裡面填寫個人識別資訊 (PII),例如電子郵件地址等。如果裝置在 Wake Lock 標記中偵測到 PII,就會記錄
_UNKNOWN,而不是您指定的標記。 - 請勿藉由程式輔助方式產生類別或方法名稱,例如藉由呼叫
getName()產生名稱等,如果嘗試透過程式輔助方式取得名稱,可能會遭到 Proguard 等工具模糊處理。請改用硬式編碼字串。 - 請勿將計數器或專用 ID 加到 Wake Lock 標籤,建立 Wake Lock 的程式碼每次執行時,都應使用相同的標記。這樣系統就能匯總每個方法的 Wake Lock 使用情形。
確認應用程式在前景顯示
Wake Lock 啟用時,裝置會消耗電力。裝置使用者應瞭解這項作業正在進行。因此,如果您使用 Wake Lock,應向使用者顯示通知。實際上,這表示您應在前景服務中取得並保留 WakeLock。前景服務必須顯示通知。
如果前景服務不適合您的應用程式,您可能也不應該使用 Wake Lock。如要瞭解在應用程式不在前景時執行工作的其他方式,請參閱「選擇合適的 API 讓裝置保持喚醒狀態」說明文件。
保持邏輯簡單
確保獲取和釋放 Wake Lock 時,盡可能使用簡單的邏輯。如果 Wake Lock 邏輯和複雜的狀態機器、逾時、執行程式集區或回呼事件有關,那麼一旦這個邏輯裡有任何不明顯的錯誤,就可能會導致 Wake Lock 保留時間超出預期。這類錯誤的診斷和偵錯作業相當困難。
確認 Wake Lock 一律會釋放
如果使用 Wake Lock,請務必確保取得的每個 Wake Lock 都正確釋放。這看似簡單,但其實不然。舉例來說,下列程式碼有問題:
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() 呼叫。結果是 Wake Lock 已取得但未釋出,這非常糟糕。
在修正後的程式碼中,doSomethingAndRelease() 可確保即使擲回例外狀況,也會釋放 Wake Lock:
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();
}
}