Intereting Posts
Как загрузить изображения из res / drawable-folder в ReactNative-App? StartService из класса, который не расширяет действие Обработчик событий для закрытия / принудительной остановки ионного приложения Ошибка «только для чтения файловой системы» при записи на SD-карту Макет для панели инструментов, перекрывающей фрагменты Бесшовный видеопоток с VideoView Андроид обнаруживает, активен ли диалог? Каков наилучший способ определения константы log TAG в Kotlin? Могу ли я проверять обновления подписки на Google Play полностью на сервере? Как определить, является ли путь локальным файлом или нет? Приложение не регистрируется в меню «Поделиться» как обработчик намерений ACTION_SEND ObjectAnimator Proxy для анимации TopMargin не может найти настройки / getter Как отслеживать пиковую память, потребляемую приложением Android Реагировать на родную гибкую коробку, не используя все доступное пространство Зависимость между тестами JUnit, которые работают на нескольких устройствах одновременно

Служба Android stopSelf (int)

Вот мой код –

public class BackgroundService extends Service { @Override public int onStartCommand(Intent intent, int flags, int startId) { super.onStartCommand(intent, flags, startId); new ServiceThread(startId); return START_NOT_STICKY; } class ServiceThread extends Thread { private int startId; ServiceThread(int startId) { this.startId = startId; } @Override public void run() { super.run(); try { Thread.sleep((long) Math.random()); } catch (InterruptedException e) { throw new RuntimeException(e); } stopSelf(startId); } } @Override public IBinder onBind(Intent intent) { return null; } } 

Согласно этой ссылке « Остановка службы », я могу / должен / должен позвонить stopSelf с полученным «startId».

Однако, если ваша служба обрабатывает несколько запросов на onStartCommand () одновременно, то вы не должны останавливать службу, когда вы закончите обработку запроса на запуск, потому что с тех пор вы могли получить новый запрос на запуск (остановка в конце первого Запрос прекратит второй). Чтобы избежать этой проблемы, вы можете использовать stopSelf (int), чтобы гарантировать, что ваш запрос на остановку службы всегда основывается на самом последнем запросе на запуск. То есть, когда вы вызываете stopSelf (int), вы передаете идентификатор запроса на запуск (startId доставляется в onStartCommand ()), которому соответствует ваш запрос на остановку. Затем, если служба получила новый запрос на запуск до того, как вы смогли вызвать stopSelf (int), тогда идентификатор не будет соответствовать, и служба не остановится.

Мой вопрос: что произойдет, если я вызову stopSelf с последним «startId», и еще какой-то более ранний старт еще не закончен. В этом случае startId будет соответствовать, и согласно этому документу служба умрет? Все остальные ранние «старты» будут просто убиты?

Если ответ «да», то какова наилучшая практика для достижения того, что служба не будет убита до тех пор, пока все более ранние старта не будут завершены.

Вчера я столкнулся с такой же проблемой. И я думаю, что нашел ответ в javadoc метода Service.stopSelfResult (int startId).

Если вы можете завершить обработку идентификаторов не по порядку (например, отправив их по отдельным потокам), вы несете ответственность за их остановку в том же порядке, который вы получили.

Это тонкая проблема – я не уверен, что какое-либо из вышеперечисленных решений является адекватным / эффективным. Решение, которое я использую, основано на классе ThreadPoolService , который расширяет Service и работает следующим образом:

  • Он определяет HashSet<Integer> который хранит startId переданный onStartCommand()
  • Он определяет поле int называемое mLastStartId которое хранит самый последний startId переданный onStartCommand()
  • Он определяет ExecutorService инициализированный либо newCachedThreadPool() либо newFixedThreadPool()
  • Он определяет метод beginIntentProcessing() который добавляет параметр startId в HashSet и записывает последний startId в mLastStartId
  • Он определяет метод endIntentProcessing() который удаляет параметр startId из HashSet и возвращает, если HashSet является пустым. Однако, если HashSet пуст, он вызывает метод stopSelf() в суперклассе Service , передавая его в mLastStartId .

Я опустил некоторые детали решения, но он эффективен и решает основную проблему, описанную выше. Я буду освещать эту тему (и многие другие) в моих будущих MOOC по параллельному программированию Android, которые описаны на http://www.coursera.org/course/posaconcurrency и http://www.coursera.org/course / Posacommunication .

Doug

Решение состоит в том, чтобы поддерживать булевскую карту хэша с идентификатором начала в качестве ключа. Затем в ваших рабочих потоках вместо вызова stopSelf(int) вызывается пользовательский метод, который выполняет следующие действия:

Установите для записи хэш-карты значение true используя идентификатор начала в качестве ключа. Перейдите по клавишам в порядке возрастания и вызовите stopSelf(key) пока не встретите false запись.