【问题标题】:How to cancel Service/IntentService/AsyncTask/Looper如何取消Service/IntentService/AsyncTask/Looper
【发布时间】:2011-11-13 09:44:13
【问题描述】:

我要疯了。 我想要一件简单的事情——我有一个很长的任务(从网络上获取几个数据对象),我想要取消它的能力。 我尝试了很多东西(很多),但没有任何效果

流程是这样的:

  1. 用户点击按钮

  2. 我开始工作(我尝试使用AsyncTaskServiceIntentServiceLooper

  3. 该任务负责处理所有事情,包括为进度更新添加持续通知

  4. 通知中的意图调用了一个新活动,她的唯一目的是取消正在进行的任务

  5. 在 cancelActivity 我尝试调用 stopService() 以获得 Service/IntentService 或执行 Looper.quit() 用于 Looper(我不记得我为 AsyncTask 尝试了什么,不知道是否有这样的 api 可以取消它)

在我看来,最好的选择是使用IntentService(我可以有几个任务排队,IntetService 会按照我想要的顺序执行)但是 我对任何类型的实现都持开放态度 - 我不在乎代码是什么,只是我可以选择取消任务

提前感谢您的帮助

医生

(我要睡觉了——在同一个问题上花 8 个小时实在是太多了)

【问题讨论】:

    标签: android service android-asynctask looper intentservice


    【解决方案1】:

    如果您在后台逻辑中无法识别停止条件,那么您使用什么特定操作来停止任务并不重要。干净地完成它的唯一方法是后台工作人员停止并善意退出。

    可用于取消后台工作的可能方案和解决方案很少。

    • 后台线程执行许多短步骤(例如带有一些循环的计算)。在这种情况下,检查操作之间的某个标志(可能是isInterrupted()),如果该标志指示操作必须停止,则退出。
    • 后台线程正在等待监视器。在后台线程上调用interrupt(),在异常处理程序中捕获异常,并采取适当的步骤干净地完成此任务并退出。
    • 后台线程正在等待 IO。在一般情况下,这个用例很难解决。如果你使用一些套接字,你可以尝试在外部关闭这个套接字并捕获异常。在最坏的情况下,您可以放弃线程,如果它曾经从 IO 返回,则它知道它已被取消并且必须丢弃 IO 结果。如果你经常这样做 - 你会耗尽内存,所以我不会真的推荐它。

    无论如何,如果你的任务不知道被停止的可能性,就没有办法(除了杀死非常糟糕的线程)来停止你的任务。

    【讨论】:

    • 感谢您的重播。由于我的任务已经在运行(连接到网站),因此使用中断()不起作用,因此它不会停止它。我将能够使用isIterrupted() 仅停止要执行的下一个对象。我没有直接打开套接字(我使用 Jsoup connect() 库来获取 html 网页来解析它)。如何关闭它?
    • 根据您自己的回答,您正在等待套接字(或做一些其他网络工作),因此中断不起作用。关闭连接管理器会终止正在关闭套接字的网络通信。
    【解决方案2】:

    好的,我设法做一些接近我想要的事情。

    我正在使用 IntentService 将我的任务排队。每个新任务都是AsyncTask。 AsyncTask 开始时为 cancelActivity 发送带有 pendingIntent 的通知。

    当点击通知时,用户会收到关于停止任务的警告弹出窗口。如果他在我的 IntentService 上单击“是”而不是我在 stopService() 上单击。

    在我添加的 IntentService 中:

        @Override
    public void onDestroy() {
        currentTask.cancel(true);
        if (mNotificationHelper != null)
            mNotificationHelper.completed();
        super.onDestroy();
        stopSelf();
    }
    

    在我添加的 AsyncTask 中:

        @Override
    protected void onCancelled() {
        isCanclled = true;
        httpClient.getConnectionManager().shutdown();
        mNotificationHelper.completed();
        if (mAsyncTaskListener != null)
            mAsyncTaskListener.AsyncTaskCanceled();
    }
    

    所以这将断开当前正在运行的所有连接。在执行工作的实际代码中,我需要捕获连接关闭的异常并处理它

    所以最后我实际上并没有停止 AsyncTask/Service,而是公开了 httpClient,这样我就可以异步断开连接了。

    我觉得有点丑但是没办法

    谢谢大家

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多