2013-11-19 3 views
4

Commonsware's WakefulIntentService работает красиво, но есть некоторые вещи, которые я не совсем понимаю. Ниже основной службы - урезанная версия source:Замечания по реализации 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?

ответ

5

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

Исправить.

Или это невозможно?

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

С учетом предыдущего следует добавить флаги & 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, возможно, «утечка» - это контекст приложения singleton, который, как одноэлементный, эффективно просочился. :-)

+0

«Если у вас есть доказательства обратного, я бы с удовольствием это увидел». - не бит, просто документы не ясно, что когда START_FLAG_RETRY установлен, START_FLAG_REDELIVERY также установлен –

+0

A-important - если сценарий, который я описываю, происходит, а onCreate (или даже Constructor, где мы 'setRedeliverIntent (true)'), не бежать - мы теряем? Или система будет запускать 'onStartCommand' с START_FLAG_RETRY? –

+1

@Mr_and_Mrs_D: «Документы не ясно, что когда START_FLAG_RETRY установлен, START_FLAG_REDELIVERY также установлен» - «START_FLAG_REDELIVERY» устанавливается, когда используется «START_REDELIVER_INTENT», и я не знаю случая, когда я когда-либо видел «START_FLAG_RETRY 'самостоятельно. «нужна ли инициализация ссылочных полей нулевому?» - Нет, это стиль личного кодирования. «если сценарий, который я описываю, произойдет» - я понятия не имею, что произойдет в этом случае, извините. – CommonsWare

1

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

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

+0

@CommonsWare: это для вас, я думаю –

Смежные вопросы