IntentService在onDestroy()被触发后仍在运行onHandleIntent()。

3
在我的偏好设置屏幕中,当单击偏好设置中的一个选项时,我希望启动一个服务来从互联网下载文件。如果该服务已经运行(正在下载文件),则应停止服务(取消下载)。
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。它直接使用HttpURLConnectionFileOutputStream进行保存。

当我点击首选项时,服务已经正确启动。现在的问题是,当我使用stopService()停止服务时,DownloadService立即触发了onDestroy();但根据日志,onHandleIntent()仍在运行,因为我仍然可以看到HTTP请求在持续进行。这是因为Service本身在一个线程中运行,还是我做错了什么?如何确保在调用stopService()onHandleIntent()中的所有内容立即停止(或至少能够停止)?

2个回答

8

最终我弄清楚了如何使它工作。

正如我在问题中所述,onHandleIntent()方法会创建一个线程来执行任务。因此,即使服务本身被销毁,线程仍然在运行。我通过添加全局变量来实现我的目标。

private static boolean isStopped = false;

转换到DownloadService类。

为了取消我的服务,不要调用

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

只需设置DownloadService.isStopped = true

最后,在onHandleIntent()中执行操作时,定期检查此布尔值以查看是否应停止下载。如果isStopped = true,立即返回并服务将停止自己。

希望这可以帮助遇到此问题的人。感谢您花时间阅读此问题。


4
为了隐藏这个isStopped变量,考虑在onDestroy中将它设置为true。 - xorgate
isStopped变量必须是公共的。代码片段将其设置为私有的。 - v01d

4

它有一个独立的线程来完成工作,取决于它正在做什么,可能无法立即停止它。如果它在I/O上阻塞,中断它可能没有效果。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接