Android 手动释放定时唤醒锁

Android 手动释放定时唤醒锁,android,wakelock,Android,Wakelock,在我的后台服务中,我使用acquire()(无参数)获取部分唤醒锁,并在我不再需要它时手动释放它 当时,一些Xperia用户抱怨Xperia的耐力模式存在问题。我发现这篇文章: 不要使用唤醒锁 唤醒锁通常对功耗非常不利,因为它们会使整个Android系统处于唤醒状态。如果使用了唤醒锁,请确保它们是定时唤醒锁,以便所使用的唤醒锁不会存在太长时间。确定唤醒锁的时间,以便在任务完成后释放唤醒锁。您可以在JavaMonday的一个示例中看到它的使用 因此,我开始使用定时唤醒锁(使用acquire(tim

在我的后台服务中,我使用
acquire()
(无参数)获取部分唤醒锁,并在我不再需要它时手动释放它

当时,一些Xperia用户抱怨Xperia的耐力模式存在问题。我发现这篇文章:

  • 不要使用唤醒锁 唤醒锁通常对功耗非常不利,因为它们会使整个Android系统处于唤醒状态。如果使用了唤醒锁,请确保它们是定时唤醒锁,以便所使用的唤醒锁不会存在太长时间。确定唤醒锁的时间,以便在任务完成后释放唤醒锁。您可以在JavaMonday的一个示例中看到它的使用
  • 因此,我开始使用定时唤醒锁(使用
    acquire(timeout)
    而不是
    acquire()
    )。问题在于发布。我仍然在手动释放,因为在大多数情况下,在超时过期之前,我不再需要锁

    问题是自动释放。我会解释的。定时采集是这样实现的(摘自android-19源代码):

    mReleaser初始化如下(来自android-19源代码):

    如果锁不再保持,则
    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);
            }
        }
    }
    
    公共无效释放(int标志){
    已同步(mToken){
    如果(!mRefCounted | |--mCount==0){
    mHandler.removeCallbacks(mReleaser);
    国际单项体育联合会(mHeld){
    试一试{
    mService.releaseWakeLock(mToken,标志);
    }捕获(远程异常){
    }
    mHeld=假;
    }
    }
    如果(mCount<0){
    抛出新的运行时异常(“锁定下的WakeLock”+mTag);
    }
    }
    }
    
    所以问题是,当我手动释放它时,它仍然试图在超时过期后自动释放它,并且唤醒锁被锁定

    问题是:如何在超时到期前手动释放定时唤醒锁的同时,仍然使用定时唤醒锁?

    作为一种解决方案(或解决方法-如果有人知道更好的解决方案,请评论)没有参考计数器的唤醒锁:

    mWakeLock.setReferenceCounted(false);
    

    这可以防止在突出显示的行上方复制的代码中锁定不足,在引用计数降至零时,删除acquire添加的回调。因此,假设您正在获取,然后每次获取仅释放一次,则应该可以。如果你真的碰到了超时,你怎么知道停止手动释放

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