遵循喚醒鎖定功能的最佳做法

使用 Wake Lock 可能會影響裝置效能。如果需要使用喚醒鎖定功能,請務必正確使用。本文將說明一些最佳做法,協助您避免常見的喚醒鎖定陷阱。

正確命名 Wake Lock

建議您在 Wake Lock 標記中加入封包、類別或方法名稱。這樣一來,如果發生錯誤,您就能更輕鬆地在原始碼中找出建立喚醒鎖定的位置。以下提供幾項額外的訣竅:

  • 請勿在名稱裡面填寫個人識別資訊 (PII),例如電子郵件地址等。如果裝置在 Wake Lock 標記中偵測到 PII,就會記錄 _UNKNOWN,而不是您指定的標記。
  • 請勿藉由程式輔助方式產生類別或方法名稱,例如藉由呼叫 getName() 產生名稱等。如果您嘗試以程式輔助方式取得名稱,可能會遭到 Proguard 等工具模糊處理。請改用硬式編碼字串。
  • 請勿將計數器或專用 ID 加到 Wake Lock 標籤,建立喚醒鎖的程式碼每次執行時都應使用相同的標記。這項做法可讓系統匯總每個方法的喚醒鎖定使用情形。

確認應用程式會顯示在前景

喚醒鎖定功能啟用時,裝置會耗用電力。裝置使用者應瞭解這項情況。因此,如果您使用 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() 呼叫。結果是喚醒鎖定已取得但未釋出,這非常糟糕。

在修正後的程式碼中,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();
    }
}