在我的后台服务中,我使用acquire()
(不带参数)获取部分唤醒锁定,并在我不再需要它时手动释放它。
那时,一些Xperia用户抱怨Xperia的Stamina模式出现问题。我发现了这篇文章:Optimizing for Sony's Stamina Mode
- 不要使用唤醒锁 唤醒锁通常对功耗非常不利,因为它们使整个Android系统保持清醒状态。如果使用了唤醒锁定,请确保它们是定时唤醒锁定,以便长时间不存在所采用的唤醒锁定。为唤醒锁定时间,以便在任务完成后释放它。您可以在Java Monday的示例中看到它。
醇>
所以我开始使用定时唤醒锁(使用acquire(timeout)
代替acquire()
)。问题在于发布。我仍在手动发布,因为在大多数情况下,我不会比超时到期更快地需要锁定。
问题是自动释放。我会解释一下。定时获取是以这种方式实现的(取自android-19来源):
public void acquire(long timeout) {
synchronized (mToken) {
acquireLocked();
mHandler.postDelayed(mReleaser, timeout);
}
}
mReleaser初始化如下(来自android-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);
}
}
}
所以问题是,当我手动释放它时,它仍然会在超时到期后尝试自动释放它,并且唤醒锁被锁定不足。
问题是:我怎样才能使用定时唤醒锁定,同时能够在超时到期之前手动释放它?
答案 0 :(得分:1)
作为解决方案(或解决方法 - 如果有人知道更好的解决方案,请发表评论)唤醒没有参考计数器的锁:
mWakeLock.setReferenceCounted(false);
这可以防止锁定不足
答案 1 :(得分:0)
在您复制的代码中,突出显示的行会删除当引用计数降为零时由acquire添加的回调,因此假设您正在获取然后每次获取只释放一次,那么您应该没问题。如果你实际上达到超时,你怎么知道停止手动释放...
if (!mRefCounted || --mCount == 0) {
mHandler.removeCallbacks(mReleaser); /// This removes the callback
if (mHeld) {
try {
mService.releaseWakeLock(mToken, flags);
} catch (RemoteException e) {
}
mHeld = false;
}
}