Commonsware的WakefulIntentService工作得很漂亮但有一些我不太了解的东西。以下是该服务的核心 - source的精简版:
class WIS extends IntentService {
private static final String NAME = WIS.class.getName() + ".Lock";
private static volatile WakeLock lockStatic = null;
synchronized private static PowerManager.WakeLock getLock(Context context) {
if (lockStatic == null) {
PowerManager mgr = (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NAME);
lockStatic.setReferenceCounted(true);
}
return (lockStatic);
}
public static void startWIS(Context ctxt, Intent i) {
getLock(ctxt.getApplicationContext()).acquire();
ctxt.startService(i);
}
public WIS(String name) {
super(name);
setIntentRedelivery(true);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
PowerManager.WakeLock lock = getLock(this.getApplicationContext());
if (!lock.isHeld() || (flags & START_FLAG_REDELIVERY) != 0) { // ?
lock.acquire();
}
super.onStartCommand(intent, flags, startId);
return (START_REDELIVER_INTENT);
}
@Override
protected void onHandleIntent(Intent intent) {
try {
// do your thing
} finally {
PowerManager.WakeLock lock = getLock(this.getApplicationContext());
if (lock.isHeld()) lock.release();
}
}
}
问题
onReceive()
返回后,该进程被终止会怎样?即如果服务onCreate()
(如果服务尚未实例化)或onStartCommand()
从未运行。 AFAIK一个被杀死的进程会锁定它。或者这是不可能的情况?(flags & START_FLAG_RETRY)
?if (!lock.isHeld())
检查?this.getApplicationContext()
?是不是this
?答案 0 :(得分:5)
AFAIK一个被杀死的进程会锁定它。
正确。
或者这是不可能的情况吗?
这是不太可能的,但肯定不是不可能的。
鉴于之前应该添加(flags& START_FLAG_RETRY)吗?
这应由START_FLAG_REDELIVERY
涵盖。 AFAIK,START_REDELIVER_INTENT
,RETRY
没有REDELIVERY
。如果你有相反的证据,我很乐意看到它。
为什么if(!lock.isHeld())检查?
在未保留的release()
上调用WakeLock
会导致异常。这只是一个安全毯,以确保我们不会抛出不必要的例外。从理论上讲,永远不需要它;理论上,我应该有头发。
为什么需要this.getApplicationContext()?这还不够吗?
我们创建了一个WakeLock
,我们将其保存在静态数据成员中。 可能 getSystemService()
来电并不会将Context
调用PowerManager
。而且,即使它确实如此,可能 Context
也不会传递给生成的WakeLock
实例。但是,为了安全起见,通过使用getApplicationContext()
,我们以一种方式获取WakeLock
,以确保我们可能“泄漏”的唯一Context
是单例应用程序上下文,单身,有效预先泄露。 : - )
答案 1 :(得分:1)
抱歉没有足够的代表发表评论,但看起来你有两个支票的竞争状态,如果(持有)释放和if(!hold)获得。即使裁判变得不稳定并不足以防守你的比赛。
这些是在不同线程上调用的复合语句。您可能希望在私有最终Object lock = new Object()上为这两个检查输入同步块,以便它们以原子方式完成。非常好的角落,但我想提到它。如果你不同意,请告诉我。感谢。