【问题标题】:How can i cancel the AsynsTask in Android?如何取消 Android 中的 AsyncTask?
【发布时间】:2014-02-12 05:56:24
【问题描述】:

嗨 onCancel 对话框我想取消对服务器的调用,但我面临的问题是,即使我取消任务,它也会访问我的服务器并修改数据。我该如何解决这个问题?下面是我的代码..

私有类 UserBoardingTask 扩展 AsyncTask { @Override 受保护的无效onPreExecute(){ progressDialog = new ProgressDialog(getActivity()); progressDialog.setMessage(getResources().getString(R.string.please_wait)); progressDialog.setIndeterminate(false); progressDialog.setCancelable(true); progressDialog.setOnCancelListener(new OnCancelListener() { @Override 公共无效onCancel(DialogInterface对话框){ if (userOnBoardingTask!= null && userOnBoardingTask.getStatus() != AsyncTask.Status.FINISHED && !userOnBoardingTask.isCancelled()) { userOnBoardingTask.cancel(true); } } }); 进度对话框.show(); } @Override 受保护的无效doInBackground(字符串... urls){ 字符串登机URL=null; 登机网址= getUrl(); UserOnBoardingDTO userOnBoardingDetailsDTO = AppStateManager.getUserBoardingDetails(); 尝试{ RestAPIManager.putToNSWebService(boardingURL, userOnBoardingDetailsDTO, username, password); } 捕获(异常 e){ errorMessage=getResources().getString(R.string.unknown_exp); } 返回空值; } @Override 受保护的无效 onCancelled() { super.onCancelled(); closeProgressDialog(); 错误消息=""; AppStateManager.setUserBoardingDetails(null); userOnBoardingTask=null; } @Override 受保护的无效onPostExecute(无效资源){ closeProgressDialog(); userOnBoardingTask=null; if(!FieldsValidator.isBlank(errorMessage)){ CommonUtil.showToast(getActivity(),errorMessage); 错误消息=""; 返回; }

【问题讨论】:

    标签: android android-asynctask


    【解决方案1】:

    偶尔检查一下isCancelled()

     protected Object doInBackground(Object... x) {
        while (/* condition */) {
          // work...
          if (isCancelled()) break;
        }
        return null;
     }
    

    另一个解决方案是

    protected void onProgressUpdate(String... progress1) {
                             if(condition){
    
                                    break;
                            }
            }
    

    【讨论】:

    • 但是 OP 在 doInBackground 中没有循环
    • 那么我已经提供了另一个解决方案,伙计
    • 然后使用第二个解决方案亲爱的
    【解决方案2】:

    将对话框移出异步任务,仅在对话框未取消时启动任务。

    【讨论】:

      【解决方案3】:

      实际上,问题不在于您的 asyncsTask 终止,而是服务器命中,如果在 asyncsTask 终止之前服务器命中已经完成,那么您也必须中断您的服务器请求。只需使用 abort 方法终止您的服务器请求。

      【讨论】:

      • 除非有一些通信问题,否则请求将被发送并可能在AsyncTask.cancel 被调用之前很长时间被传递 - 至少这不是非常可预测的行为。无论如何调用 abort() 是个好主意,具体取决于 RestAPIManager 实现中的内容。
      【解决方案4】:

      userOnBoardingTask 是在哪里声明的,它在哪里分配给正在运行的任务的引用?我怀疑当任务尝试取消它时,它没有存储正确的引用。

      我不确定这是否是您问题的真正原因。但是可以肯定的是,如果它打算在当前任务中进行品脱,你可以摆脱这个变量。只需更改对话框的取消侦听器:

      private class UserBoardingTask extends AsyncTask<String, Void, Void> {
      
      @Override
      protected void onPreExecute() {
      
          // ...
      
          progressDialog.setOnCancelListener(new OnCancelListener() {
      
              @Override
              public void onCancel(DialogInterface dialog) {
                  if (UserBoardingTask.this.getStatus() != AsyncTask.Status.FINISHED 
                      && UserBoardingTask.this.isCancelled()) {
                      UserBoardingTask.this.cancel(true);
                  }
              }
          });
      

      事实上,你可以省略UserBoardingTask.this 短语,因为内部类可以直接指向嵌套类的字段,只要名称不会被内部类成员的名称所掩盖:

      private class UserBoardingTask extends AsyncTask<String, Void, Void> {
      
      @Override
      protected void onPreExecute() {
      
          // ...
      
          progressDialog.setOnCancelListener(new OnCancelListener() {
      
              @Override
              public void onCancel(DialogInterface dialog) {
                  if (getStatus() != AsyncTask.Status.FINISHED && isCancelled()) {
                      cancel(true);
                  }
              }
          });
      

      编辑

      还有一点是,在向服务器发送请求之前,您可以检查doInBackground 内部,您可以检查任务是否没有被取消

              // ...
      
              @Override
              protected Void doInBackground(String... urls) {
      
                  // ...
      
                  try {
                      if(isCancelled()) {
                         throw new Exception("Exit: task cancelled!");
                      }
      
                      RestAPIManager.putToNSWebService(boardingURL, userOnBoardingDetailsDTO, username, password);
      
                  // ...
      

      【讨论】:

      • 我已将 AsyncTask 引用声明为私有静态 UserOnBoardingTask userOnBoardingTask;我的 Fragment 和按钮上的变量单击实例化它。
      • 如果它是静态的而不是实例变量:)。它在哪里分配了运行任务的引用?
      • 你能显示代码吗 - 周围有一些“上下文代码”:)
      • 私有静态 NorthStarUserOnBoardingTask userOnBoardingTask; //在 frgagment 和按钮上单击调用 userOnBoardingTask=new NorthStarUserOnBoardingTask(); userOnBoardingTask.execute();
      • 好吧,看来我的建议不能解决你的问题,但无论如何你可以用它来让你的代码“更干净”。
      【解决方案5】:
      RestAPIManager.putToNSWebService(boardingURL, userOnBoardingDetailsDTO, username, password);
      

      上面的代码命中了服务器。所以你必须在取消之间验证代码的执行。

      试试这样的

        try{
      if(!userOnBoardingTask.isCancelled())
      {
                      RestAPIManager.putToNSWebService(boardingURL, userOnBoardingDetailsDTO, username, password);
      }
      
                  }   
      
      
                     catch (Exception e) {
                     errorMessage=getResources().getString(R.string.unknown_exp);
                      }
      

      没关系。如果用户在执行 ResetAPIManager 代码之前取消任务。假设用户在发起服务器调用后尝试取消任务,您必须告诉已经修改或重新修改服务器数据或无法取消或向用户发送一些消息。所有这些都是通过获取服务器响应并验证服务器响应是否更改来完成的。

      使用类似的东西

       Var rsponse = RestAPIManager.putToNSWebService(boardingURL,userOnBoardingDetailsDTO, username, password);
      

      在 onPostExecute() 或 OnCancelled() 方法中验证响应消息。

      【讨论】:

        【解决方案6】:

        如果你在访问此方法后取消异步任务 RestAPIManager.putToNSWebService(boardingURL,userOnBoardingDetailsDTO, username, password); async 任务将在运行上述代码后取消,因此您应该通过在 RestAPIManager 类中创建一个新方法并在您的 asyncTask 中调用 OnCancelled 方法中的该方法来纠正此问题。

        【讨论】:

          【解决方案7】:

          简短回答:不可能通过简单的取消来停止数据发布。一旦异步任务运行,即使您在中途取消它也会发生数据发布。可以在简单运行中完成取消 检查这篇文章 [Android - Cancel AsyncTask Forcefully

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-06-12
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多