IntentService onHandleIntent() все еще работает после запуска onDestroy()

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

public class Setting extends PreferenceActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    downloadPref.setOnPreferenceClickListener(new OnPreferenceClickListener() {

        @Override
        public boolean onPreferenceClick(Preference pref) {
            if (DownloadService.isRunning) {
                Setting.this.stopService(new Intent(Setting.this,
                    DownloadService.class));
            } else {
                Setting.this.startService(new Intent(Setting.this,
                    DownloadService.class));
            }
            return false;
        }
    });
    }
}

Класс обслуживания:

public class DownloadService extends IntentService {

public static final int DOWNLOAD_SUCCESS = 0;
public static final int DOWNLOAD_FAIL = 1;
public static final int DOWNLOAD_CANCELLED = 2;
public static final int SERVER_FAIL = 3;

public static boolean isRunning = false;
private int result;

public DownloadService() {
    super("DownloadService");
}

@Override
public void onCreate() {
    super.onCreate();
    isRunning = true;
}

@Override
protected void onHandleIntent(Intent intent) {
    if (NetworkStateUtils.isInternetConnected(getApplicationContext())) 
        result = downloadFiles(getApplicationContext());

}

@Override
public void onDestroy() {
    super.onDestroy();
    switch (result) {
    case DOWNLOAD_SUCCESS:
        Toast.makeText(getApplicationContext(), R.string.download_finished,
                Toast.LENGTH_SHORT).show();
        break;
    case DOWNLOAD_CANCELLED:
        Toast.makeText(getApplicationContext(), R.string.download_canceled,
                Toast.LENGTH_SHORT).show();
        break;
    case DOWNLOAD_FAIL:
        Toast.makeText(getApplicationContext(), R.string.download_failed,
                Toast.LENGTH_SHORT).show();
        break;
    }
    isRunning = false;
}
}

Эта служба предназначена для работы до завершения загрузки. Функция downloadFiles() не использует AsyncTask. Он сохраняет HttpURLConnection напрямую с FileOutputStream.

Служба запускается правильно, когда я нажимаю на предпочтение. Теперь проблема в том, что когда я нажимаю, чтобы остановить службу с помощью stopService(), DownloadService немедленно запускает onDestroy(); однако, согласно журналам, onHandleIntent() все еще работает, потому что я все еще постоянно вижу HTTP-запросы. Это потому, что Service работает в самом потоке, или я что-то не так делаю? Как я могу гарантировать, что все в onHandleIntent() немедленно остановится (или, по крайней мере, сможет остановиться) при вызове stopService()?


person Lawrence Choy    schedule 17.10.2012    source источник


Ответы (2)


Наконец-то понял, как заставить его работать.

Как я уже говорил в своем вопросе, onHandleIntent() каким-то образом создаст поток для выполнения этой работы. Таким образом, даже когда сама служба уничтожена, поток все еще работает. Я достиг своей цели, добавив глобальную переменную

private static boolean isStopped = false;

в DownloadService класс.

Чтобы отменить мою услугу, вместо того, чтобы звонить

Setting.this.stopService(new Intent(Setting.this, DownloadService.class));

просто установите DownloadService.isStopped = true.

Наконец, выполняя действия в onHandleIntent(), периодически проверяйте это логическое значение, чтобы увидеть, должно ли оно прекратить загрузку. Если isStopped = true, немедленно вернитесь, и служба остановится сама.

Надеюсь, это поможет кому-то, кто тоже столкнулся с этой проблемой. И спасибо за ваше время, читая этот вопрос.

person Lawrence Choy    schedule 18.10.2012
comment
Чтобы скрыть эту переменную isStopped, установите для нее значение true в onDestroy. - person xorgate; 22.01.2013
comment
Переменная isStopped должна быть общедоступной. Фрагмент кода устанавливает его как частный. - person v01d; 12.08.2015

У него есть отдельный поток для выполнения работы, и в зависимости от того, что он делает, может быть невозможно остановить его немедленно. Если он блокирует ввод-вывод, его прерывание, скорее всего, не будет иметь никакого эффекта.

person Nikolay Elenkov    schedule 17.10.2012