Страницы

Поиск по вопросам

понедельник, 6 января 2020 г.

Потоки и IntentService

#android #android_service #android_threads


В каком потоке происходит работа IntentService? Вроде как по определению это подкласс
обычного Service, у которого метод onHandleIntent отрабатывает в background потоке:


  Clients send requests through Context.startService(Intent) calls; the
  service is started as needed, handles each Intent in turn using a
  worker thread, and stops itself when it runs out of work.


...


  All requests are handled on a single worker thread -- they may take as
  long as necessary (and will not block the application's main loop),
  but only one request will be processed at a time.


Но правильно ли я понимаю, что всё равно сам IntentService работает в главном (UI)
потоке, и из него уже запускает новый worker/background-поток? И при завершении приложения
IntentService будет убит вместе со всем приложением, до конца выполнится только текущий
метод onHandleIntent, но следующий уже не будет запущен?

К примеру, если в активити есть следующий код:

for (int i = 0; i < 5; i++) {
   Intent intent = new Intent(this, MyIntentService.class);
   this.startService(intent);
}


и приложение завершается, когда весь цикл выполнен, но метод onHandleIntent отработал
только один раз, то больше метод onHandleIntent вызван не будет?

UPD

Например, если говорить об исходном коде класса IntentService:

public abstract class IntentService extends Service {
   ...
   @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
    ...
    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }
    ...
    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}


Правильно ли я понимаю, что в этом случае (в примере с циклом) метод onStartCommand
выполнится 5 раз, и вызовет 5 раз метод onStart, который с помощью mServiceHandler
помещает intent-ы в очередь, но при завершении main-потока умирает вместе с ним?..
    


Ответы

Ответ 1



В каком потоке происходит работа IntentService? работа IntentService происходит в отдельном Thread, который создается во время создания сервиса, все остальные Message будут поститься на Looper от этого треда, те получается что это SingleQueue. Но правильно ли я понимаю, что всё равно сам IntentService работает в главном (UI)? Не совсем точно. По умолчанию все компоненты одного приложения работают в одном процессе, но вам никто не помешает запустить сервис из другого потока, внутри себя он создаст поток из контекста который вы передадите. Как только процесс завершится поток сервиса умрет. И при завершении приложения IntentService будет убит вместе со всем приложением, до конца выполнится только текущий метод onHandleIntent, но следующий уже не будет запущен? Да. Но подмечу если компоненты одного приложения работают в одном процессе. и приложение завершается, когда весь цикл выполнен, но метод onHandleIntent отработал только один раз, то больше метод onHandleIntent вызван не будет? не факт, здесь работа разных потоков может успеть вызываться, а может нет. Смотря как быстро вы убиваете процесс. Смею предположить если сделать, что-то типо System.exit(0) то не успеет даже 1-раз вызваться. Правильно ли я понимаю, что в этом случае (в примере с циклом) метод onStartCommand выполнится 5 раз, и вызовет 5 раз метод onStart, который с помощью mServiceHandler помещает intent-ы в очередь, но при завершении main-потока умирает вместе с ним?. Да.

Ответ 2



И я решила ещё проверить на практике свои предположения, для этого создала класс, аналогичный IntentService, добавив в методы этого класса только логирование, и добавила логирование в цикл: for (int i = 0; i < 5; i++) { Log.i(LOG_TAG, "Cycle: " + i); Intent intent = new Intent(this, TestService.class); startService(intent); } В результате получила следующий вывод: Cycle: 0 Cycle: 1 Cycle: 2 Cycle: 3 Cycle: 4 IntentServiceWithLog onStartCommand IntentServiceWithLog onStart TestService onHandleIntent IntentServiceWithLog onStartCommand IntentServiceWithLog onStart IntentServiceWithLog onStartCommand IntentServiceWithLog onStart TestService onHandleIntent IntentServiceWithLog onStartCommand IntentServiceWithLog onStart IntentServiceWithLog onStartCommand IntentServiceWithLog onStart TestService onHandleIntent TestService onHandleIntent TestService onHandleIntent И если ещё добавить в эти методы логирование имени потока: Log.i("THREAD", Thread.currentThread().getName()); гипотеза тоже подтверждается: IntentServiceWithLog onStartCommand THREAD: main IntentServiceWithLog onStart THREAD: main TestService onHandleIntent THREAD: IntentService[TestService]

Комментариев нет:

Отправить комментарий