2014-02-28 92 views
3

在我的後臺服務中,我使用acquire()(不帶參數)獲取部分喚醒鎖,並在我不再需要時手動釋放它。手動釋放定時WakeLock

當時,一些Xperia用戶抱怨Xperia的Stamina模式存在問題。我發現這篇文章:Optimizing for Sony's Stamina Mode

  1. 不要使用喚醒鎖定 喚醒鎖一般爲功耗相當糟糕,因爲他們保持整個Android系統的清醒。如果使用喚醒鎖,請確保它們是定時喚醒鎖,以便採取的喚醒鎖長時間不存在。定時喚醒鎖定,以便在任務完成後釋放它。您可以在Java Monday的示例中看到它。

所以我使用定時喚醒鎖定(使用acquire(timeout)代替acquire())開始。問題在於發佈。我仍然手動釋放,因爲在大多數情況下,我不再需要鎖定,而是超時將過期。

問題是自動發佈。我會解釋。定時獲取被實現這種方式(從機器人-19來源的截取):

public void acquire(long timeout) { 
    synchronized (mToken) { 
     acquireLocked(); 
     mHandler.postDelayed(mReleaser, timeout); 
    } 
} 

mReleaser被初始化爲以下(從機器人-19源):

private final Runnable mReleaser = new Runnable() { 
    public void run() { 
     release(); 
    } 
}; 

而且release()拋出的RuntimeException如果鎖不再舉行:

public void release(int flags) { 
    synchronized (mToken) { 
     if (!mRefCounted || --mCount == 0) { 
      mHandler.removeCallbacks(mReleaser); 
      if (mHeld) { 
       try { 
        mService.releaseWakeLock(mToken, flags); 
       } catch (RemoteException e) { 
       } 
       mHeld = false; 
      } 
     } 
     if (mCount < 0) { 
      throw new RuntimeException("WakeLock under-locked " + mTag); 
     } 
    } 
} 

所以問題是,當我手動釋放它,它仍然會嘗試超時過期後自動釋放,一個喚醒鎖被鎖定。

現在的問題是:如何在超時過期之前手動釋放它,還能如何使用定時喚醒鎖?

回答

1

作爲一個解決方案(或解決 - 如果有人知道更好的解決方案請評論)喚醒鎖沒有引用計數器:

mWakeLock.setReferenceCounted(false); 

這可以防止在鎖定

0

在你上面複製的代碼當參考計數下降到零時,突出顯示的行將刪除通過獲取添加的回調,因此假設您正在獲取然後每次獲取釋放一次,那麼您應該應該沒問題。如果你真的達到超時,但你怎麼知道停止手動釋放...

if (!mRefCounted || --mCount == 0) { 
    mHandler.removeCallbacks(mReleaser);   /// This removes the callback 
    if (mHeld) { 
     try { 
      mService.releaseWakeLock(mToken, flags); 
     } catch (RemoteException e) { 
     } 
     mHeld = false; 
    } 
}