Монблан окна

10.09.2017


Мы рассматривали главный поток и роль обработчиков. В связи с этим очень полезно изучить реализацию исходного кода IntentService в SDK. Это поможет понять, как обработчики и главный поток применяются для создания длительно выполняющейся службы, использующей рабочий поток. Анализ кода IntentService поможет также понять абстракцию, которая будет рассмотрена далее в этой главе в разделе “Длительно выполняющийся приемник”, и которая представляет собой усовершенствование IntentService.


Рассмотрим исходный код IntentService (взятый из дистрибутива исходного кода Android), показанный в листинге 19.10.


1. В методе опСгеаЬе() службы создается отдельный рабочий поток. Как правило, рабочие потоки запускаются в методе onStartCommand() службы. Однако это привело бы к существованию нескольких рабочих потоков, по одному для каждого вызова зЬагЬЗегу1се(). Для 1пЬепЬБегу1се желательно наличие единственного рабочего потока, обслуживающего все вызовы startService(), поэтому мы устанавливаем рабочий поток в методе onCreate(), который вызывается только один раз — когда служба помещается в память (это не полностью идентично одиночному потоку, но подобно ему). Возможно вам понадобятся монблан окна.


2. В этом рабочем потоке создается конструктор цикла (и, следовательно, очередь для получения и диспетчеризации сообщений). Это позволяет одному и тому же рабочему потоку отвечать на многие сообщения друг за другом, не требуя создания нового рабочего потока для каждого запроса.


3. В рабочем потоке устанавливается дескриптор, чтобы главный поток службы мог отбросить сообщение через обработчик. Мы нуждаемся в этом рабочем потоке, поскольку каждый раз, когда клиент использует startService(), этот вызов поступает в главный поток 1пЬепЬ5е^1се, который не должен задерживаться. Мы нуждаемся в механизме для помещения этого запроса в очередь, чтобы рабочий поток мог его обработать, когда он становится доступным. Это выполнимо при наличии обработчика рабочего потока в главном потоке. Обратите внимание на метод onStart(), который функционирует в главном потоке. Чтобы удостовериться в этом, достаточно переопределить этот метод и вызвать его родителя во время регистрации сигнатуры потока. Вы увидите, что onStart() действует в главном потоке, а опНап41еМеззаде() — во вторичном рабочем потоке.


4. И, наконец, когда onHand1eIntent() будет осуществлять возврат, обработчик вызовет метод stopSe1f() службы. Остановка службы с помощью stopSe1f() пройдет успешно при отсутствии каких-либо ожидающих сообщений. Метод stopSe1f () обеспечивает подсчет ссылок. Это означает, что количество его вызовов должно совпадать с числом обращений к startService(). Именно это является причиной вызова stopSe1f() после каждого вызова startService().