Усовершенствования реализации WakefulIntentService

Commonsware's WakefulIntentService работает красиво, но есть некоторые вещи, которые я не совсем понимаю. Ниже приведена ядро ​​службы – урезанная версия источника :

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 недостаточно?

AFAIK убил процесс, запустив его блокировки.

Верный.

Или это невыполнимый сценарий?

Это маловероятно, но, конечно, не невозможно.

С учетом предыдущего следует добавить (флаги & START_FLAG_RETRY)?

Это должно быть охвачено START_FLAG_REDELIVERY . AFAIK, с START_REDELIVER_INTENT , нет RETRY без REDELIVERY . Если у вас есть доказательства обратного, я бы с удовольствием это увидел.

Почему проверка if (! Lock.isHeld ())?

Вызов release() в WakeLock который не удерживается, приводит к исключению. Это просто защитное одеяло, чтобы гарантировать, что мы не забросим ненужное исключение. Теоретически он никогда не понадобится; В теории у меня должны быть волосы.

Зачем нужен this.getApplicationContext ()? Разве этого недостаточно?

Мы создаем WakeLock , который мы держим в статическом элементе данных. Вероятно, getSystemService() не getSystemService() создание Context который вызвал его внутри PowerManager . И даже если бы это произошло, возможно, Context не будет передан в результирующий экземпляр WakeLock . Однако, чтобы быть в безопасности, используя getApplicationContext() , мы получаем WakeLock таким образом, чтобы гарантировать, что единственным Context мы могли бы «протекать», является контекст приложения singleton, который, как одноэлементный, эффективно просочился. 🙂

Извините, у вас недостаточно комментариев для комментариев, но похоже, что у вас есть состояние гонки с двумя проверками, если (удерживается) релиз и если (!). Т.е. сделать ref volatile недостаточно, чтобы охранять вас от рас.

Это составные операторы, вызываемые для разных потоков. Вероятно, вы захотите ввести блок синхронизации для закрытого конечного объекта Object lock = new Object () для этих двух проверок, чтобы они выполнялись атомарно. Очень угловой, но я подумал, что упомянул об этом. Дайте мне знать, если вы не согласны. Благодарю.

Intereting Posts
Android, как получить SNR (отношение сигнал / шум) Цвет фона на холсте Android (приложение Canvas) Создание приложения с встроенным CrossWalk Застрял на экране «Подключение к WiFi» при настройке устройства Android Lollipop Cordova APP – Можно ли показывать подачу камеры в контейнере? Ошибка при выполнении exec (). Команда: Рабочий каталог: null Окружающая среда: null – как правильно выполнить двоичный код в Android на некорректном устройстве? Размер скриншотов для публикации приложения для Android в Google Play Как получить событие завершения вызова в Android-приложении Может ли операция получать намерение неупорядоченного вещания (входящего вызова) до приемника по умолчанию системы? Как загрузить изображение в Parse в Android? TextView полужирный через xml-файл? Импорт com.google.android.vending не может быть разрешен в импортированном проекте Android Карта Google в Android, отображение в малом размере API проезда на Android Как вызвать активность на основе активности Java?