【问题标题】:How to run the same asynctask more than once?如何多次运行同一个异步任务?
【发布时间】:2011-07-29 22:16:26
【问题描述】:

我在活动第一次启动时运行我的 asyncTask,然后如果网络连接不可用,那么我有一个刷新按钮尝试运行 asyncTask 以重试。但是我得到一个调试错误说这个..

07-29 18:14:21.290: ERROR/AndroidRuntime(9080): FATAL EXCEPTION: main
07-29 18:14:21.290: ERROR/AndroidRuntime(9080): java.lang.IllegalStateException: Cannot execute task: the task has already been executed (a task can be executed only once)
   07-29 18:14:21.290: ERROR/AndroidRuntime(9080):     at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:541)
   07-29 18:14:21.290: ERROR/AndroidRuntime(9080):     at android.os.AsyncTask.execute(AsyncTask.java:499)
  07-29 18:14:21.290: ERROR/AndroidRuntime(9080):     at com.fttech.gameIT.MainMenu$1.onClick(MainMenu.java:90)

无论如何要运行两次?

【问题讨论】:

    标签: android


    【解决方案1】:

    只需创建另一个实例并执行它。

    【讨论】:

    • 我知道,但问题是如果用户多次点击按钮...然后它只会执行一次,然后在第二次点击后强制关闭
    • 禁用按钮直到AsyncTask 回来?顺便说一句,这是正确的方法,需要生成一个新的AsyncTask
    • 把它变成一个单例 if (task != null then) make and run task
    • 你能在你的答案中加入一个例子吗?
    • 哪部分不明白?如果你愿意,我可以解释得更好。
    【解决方案2】:

    就像线程一样,AsyncTasks 不能重复使用。每次要运行一个实例时,都必须创建一个新实例。

    【讨论】:

      【解决方案3】:

      你永远不能再次执行线程,不能用Java,不能用任何其他语言,一旦用run()方法完成线程,你就不能重新启动它,这就是你得到IllegalStateException的原因.

      您仍然可以在该线程上调用方法,但它们将在调用它们的线程上运行不能在不同的线程上。因此,您将不得不创建一个新的。

      【讨论】:

      • Hmmm..好吧,那行不通..因为onClick..让我们说如果用户继续点击它..它将运行一次并给出强制关闭错误..无论如何有一个使应用程序关闭然后再打开的按钮?或者重新加载一个活动?
      • @Coder_For_Life22 处理双击的方式是忽略对按钮的任何其他点击并在单击一次后更改其外观。
      • 我不明白你的意思?
      • @coder_For_Life22 我不确定您遇到了什么问题,但我的理解是问题与用户双击有关,我的意思是您应该忽略任何双击.
      • 我可以在让按钮可用之前测试条件
      【解决方案4】:

      您不能多次运行同一个 AsyncTask 实例。 假设您有一个名为 MyAsyncTaks 的 AsyncTask,并且您打算做这样的事情,

          MyAsyncTask myAsyncTask = new MyAsyncTaks();
          myAsyncTask.execute(); // Works as expected
          .
          .
          .
          .
          myAsyncTask.execute(); // This will throw you exception
      

      这样做的原因是,一个线程一旦完成了它的'run'方法,就不能被分配另一个任务。在这里,在第一次调用 execute() 时,您的 AsyncTask 开始运行并且 完成工作后,线程退出运行。当然,下次调用 execute() 会抛出异常。

      多次运行它的最简单方法是创建一个新的 MyAsyncTaks 实例并在其上调用 execute。

          MyAsyncTask myAsyncTask = new MyAsyncTaks();
          myAsyncTask.execute(); // Works as expected
          .
          .
          .
          MyAsyncTask myAsyncTask2 = new MyAsyncTaks();
          myAsyncTask2.execute(); // Works as expected
      

      虽然这里不需要提及,但必须注意,在 Android SDK 版本 Honeycomb 之后,如果您一次运行多个 AsyncTask,它们实际上会运行 依次。如果要并行运行它们,请改用 executeOnExecutor。

      【讨论】:

      • myAsyncTask = new MyAsyncTaks();myAsyncTask.execute(); 会起作用吗?
      【解决方案5】:

      只需进行新的调用,例如 new asyncTask().execute();您必须创建一个新对象才能重新启动该任务。

      【讨论】:

      • @Darrell:没用,除非你更详细地描述你做了什么,出了什么问题。
      【解决方案6】:

      我只是创建了异步任务,然后创建了一个可运行的对象来创建异步任务的新实例。然后,您可以一遍又一遍地向处理程序提交您的可运行文件。

      class MyAsyncTask extends AsyncTask<String, Void, String>{ ...}
      
      Runnable myRunner = new Runnable(){
           public void run() {
              new MyAsyncTask ().execute(...);
      }};
      myHandler.post(myRunner);
      

      【讨论】:

      • 仍在创建异步任务的新对象。最好在没有 runnable 的情况下使用它
      【解决方案7】:

      这解决了我的问题:

      public class MainActivity extends AnimationActivity {
      
          MyAsyncTasks asyncTasks = new MyAsyncTasks();
      
          @BindView(R.id.refresh_btn)
          Button refreshBtn;
      
          @Override
          public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_main);
              setUnbinder(ButterKnife.bind(this));  // ButterKnife usage
      
              syncTasks();  // run asyncTasks on activity start
      
              refreshBtn.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      syncTasks(); // run asyncTasks on button click
                  }
              });
          }
      
          private void syncTasks() {
              try {
                  if (asyncTasks.getStatus() != AsyncTask.Status.RUNNING){   // check if asyncTasks is running
                      asyncTasks.cancel(true); // asyncTasks not running => cancel it
                      asyncTasks = new MyAsyncTasks(); // reset task
                      asyncTasks.execute(); // execute new task (the same task)
                  }
              } catch (Exception e) {
                  e.printStackTrace();
                  Log.e("MainActivity_TSK", "Error: "+e.toString());
              }
          }
      }
      

      【讨论】:

      • 欢迎堆栈溢出!请解释您的代码,以便其他用户能够很好地理解。
      【解决方案8】:

      你可以这样做:

      private MyAsyncTask createAsyncTask(){
          if (myAsyncTask == null){
              return myAsyncTask = new MyAsyncTask();
          }
              myAsyncTask.cancel(true);
              return myAsyncTask = new MyAsyncTask();
       }
      

      然后你就可以使用它了:

      createAsyncTask().execute();
      

      这每次都会为您的后台任务创建一个新实例。

      【讨论】:

        【解决方案9】:

        @coder_For_Life22 我认为答案迟到了,无论如何你可以这样做

            @Override
            protected void onPostExecute(Void a) {
        
                myAsyncTask=new MyAsyncTask();
            }
        

        为了在执行后启动一个新的 AsyncTask :)

        【讨论】:

          【解决方案10】:

          异步 ​​tsk 只运行一次,因为异常表明任务已经执行。 所以你只需要创建一个新的异步实例,然后调用.execute(); 为了再次运行它..谢谢你

          【讨论】:

            【解决方案11】:

            我创建了一个 ProgressUpdater 类型的 Arraylist(扩展 AsyncTask 的类的名称)并将实例添加到其中(在按钮的 onClick 中)。因此,您可以在需要时执行和取消这些任务。

            public class MainActivity extends Activity {
            ProgressBar progress;
            ProgressUpdater task;
            ArrayList<ProgressUpdater> pu = new ArrayList<MainActivity.ProgressUpdater>();
            int count = 0;
            
            @Override
            protected void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);
                setContentView(R.layout.activity_main);
                progress = (ProgressBar) findViewById(R.id.progress);
            
            }
            
            public void onClick(View v) {
                switch (v.getId()) {
                case R.id.btn:
                    task = new ProgressUpdater();
                    pu.add(task);
                    count++;
                    pu.get(count - 1).execute(0);
                    System.out.println("task" + task);
            
                    // task.execute(10);
                    break;
                case R.id.btnCancel:
                    if (count >= 0) {
                        pu.get(count - 1).cancel(true);
                        pu.remove(count - 1);
                        count--;
                    }
                    // task.cancel(true);
            
                    break;
            
                }
            }
            
            @Override
            public boolean onCreateOptionsMenu(Menu menu) {
                // Inflate the menu; this adds items to the action bar if it is present.
                getMenuInflater().inflate(R.menu.main, menu);
                return true;
            }
            
            private class ProgressUpdater extends AsyncTask<Integer, Integer, Void> {
                @Override
                protected void onPreExecute() {
                    // TODO Auto-generated method stub
                    super.onPreExecute();
                    progress = (ProgressBar) findViewById(R.id.progress);
                    progress.setMax(100);
                }
            
                @Override
                protected Void doInBackground(Integer... params) {
                    // TODO Auto-generated method stub
                    int start = params[0];
                    for (int i = start; i <= 100; i++) {
                        try {
                            boolean cancelled = isCancelled();
                            if (!cancelled) {
                                publishProgress(i);
                                SystemClock.sleep(100);
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                    return null;
                }
            
                @Override
                protected void onPostExecute(Void result) {
                    // TODO Auto-generated method stub
                    super.onPostExecute(result);
                    Log.v("Progress", "Finished");
                }
            
                @Override
                protected void onCancelled() {
                    // TODO Auto-generated method stub
                    super.onCancelled();
                    progress.setMax(0);
            
                }
            
                @Override
                protected void onProgressUpdate(Integer... values) {
                    // TODO Auto-generated method stub
                    super.onProgressUpdate(values);
                    progress.setProgress(values[0]);
                }
            
            }
            

            }

            【讨论】:

              【解决方案12】:

              在你的 MainActivity 中你可以这样写:

              LeoAsyncTask leoAsyncTaskGeneric;
              
              
              public void onClick_AsyncTask(View view) {
              
                  LeoAsyncTask leoAsyncTaskInner = new LeoAsyncTask();
                  leoAsyncTaskInner.execute();
              
                  leoAsyncTaskGeneric=leoAsyncTaskInner; 
              

              }

              /**如果你在 AsyncTask 类的内存中创建一个空间作为泛型,那么你可以在 onClick 方法中创建同一个类的实例,并且有等号,所以每次你按下 onClick 你都会使用 Class AsyncTask 的新实例,它不会给您带来问题 */

              【讨论】:

                【解决方案13】:

                您可以在按下按钮时取消 asyncTask,然后再次执行它。

                内部 OnClic 方法:

                asyncTask.cancel();
                AsyncTask asyncTask = new AsyncTask();
                asyncTask.execute();
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-04-15
                  • 1970-01-01
                  • 2016-12-16
                  相关资源
                  最近更新 更多