如何多次运行相同的asynctask?

时间:2011-07-29 22:16:27

标签: android

我在活动首次启动时运行了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)

无论如何都要运行两次?

13 个答案:

答案 0 :(得分:72)

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

答案 1 :(得分:33)

就像线程一样,AsyncTask s无法重用。每次要运行一个实例时,都必须创建一个新实例。

答案 2 :(得分:16)

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

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

答案 3 :(得分:5)

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

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

原因是,一个线程一旦完成其“运行”方法,就无法分配另一个任务。这里,在第一次调用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,它们实际运行 顺序。如果要以parallally方式运行它们,请改用executeOnExecutor。

答案 4 :(得分:4)

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

答案 5 :(得分:3)

我只是创建了asynctask然后创建了一个runnable,它创建了asynctask的新实例。然后,您可以反复向处理程序提交runnable。

class MyAsyncTask extends AsyncTask<String, Void, String>{ ...}

Runnable myRunner = new Runnable(){
     public void run() {
        new MyAsyncTask ().execute(...);
}};
myHandler.post(myRunner);

答案 6 :(得分:0)

我创建了一个类型为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]);
    }

}

}

答案 7 :(得分:0)

在您的MainActivity中,您可以这样说:

LeoAsyncTask leoAsyncTaskGeneric;


public void onClick_AsyncTask(View view) {

    LeoAsyncTask leoAsyncTaskInner = new LeoAsyncTask();
    leoAsyncTaskInner.execute();

    leoAsyncTaskGeneric=leoAsyncTaskInner; 

}

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

答案 8 :(得分:0)

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

OnClic方法:

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

答案 9 :(得分:0)

这解决了我的问题:

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());
        }
    }
}

答案 10 :(得分:0)

您可以这样做:

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

然后您可以使用它:

createAsyncTask().execute();

这每次都会成为后台任务的新实例。

答案 11 :(得分:0)

@ coder_For_Life22我认为答案来晚了,无论如何您都可以做到

    @Override
    protected void onPostExecute(Void a) {

        myAsyncTask=new MyAsyncTask();
    }

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

答案 12 :(得分:-1)

线程规则

  • 必须在UI线程上加载AsyncTask类。这个完成了 自JELLY_BEAN起。
  • 必须在UI线程上创建任务实例。 必须在UI线程上调用execute(Params ...)。
  • 不要手动调用onPreExecute(),onPostExecute(Result),doInBackground(Params ...),onProgressUpdate(Progress ...)。
  • 任务只能执行一次(如果尝试第二次执行则会抛出异常。)

有关详细信息,请查看此link