WakeLock仍在举行时完成

Tim*_*aly 20 android wakelock android-activity

pmkeepScreenOn变量是全局定义.

我在OnCreate方法中获取了PowerManager.WakeLock:

pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
keepScreenOn = pm.newWakeLock(PowerManager.SCREEN_BRIGHT_LOCK,"tpd");
Run Code Online (Sandbox Code Playgroud)

在我的onStart,onResume和onRestart中我抓住了锁

if (keepScreenOn == null) {
    keepScreenOn = pm.newakeLock(PowerManager,SCREEN_BRIGHT_LOCK,"tpd");
}
keepScreenOn.acquire();
Run Code Online (Sandbox Code Playgroud)

在我的onDestroy,onPause和onStop中,我发布了锁定:

if (keepScreenOn != null) {
  keepScreenOn.release();
  keepScreenOn = null
}
Run Code Online (Sandbox Code Playgroud)

我的应用程序退出后,我得到一个失败的屏幕,adb抱怨

java.lang.Exception:WakeLock在仍然持有时完成:tpd

跟踪显示我在退出前释放了锁.我错过了什么?

有没有办法退出应用,而不穿过的至少一个 onPause,onStoponDestroy.我可以看到应用程序 release()经常被称为acquire(),因此即使唤醒锁被引用计数,它仍然应该没有引用.

小智 29

好的,我相信我发现了问题.

WakeLock是引用计数.这意味着如果第二次acquire() 发生,它只会碰到引用计数.每次呼叫都acquire() 需要通过以下呼叫进行保护isHeld():

if ((keepScreenOn != null) &&           // we have a WakeLock
    (keepScreenOn.isHeld() == false)) {  // but we don't hold it 
  keepScreenOn.acquire();
}
Run Code Online (Sandbox Code Playgroud)

我曾经假设acquire()在锁定时我没有做任何事情,因此多次acquire()通话导致问题.由于引用计数不为零,因此GC会引发错误.


小智 0

不,全局范围内只有一个声明,并且对 acquire() 和 release() 的所有调用都发生在该范围内。当它们发生时我 println 并且 acquire() 发生一次并且释放发生一次。