开发者

How to run the same asynctask more than once?

I have my asyncTask run when the activity first starts, then if network connectivity is not available then i have a refresh button that tries to run the asyncTask to try again. But i get a debug error saying this..

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)

Is there anyway to run this twice?


Just create another instance and execute it.


Just like threads, AsyncTasks can't be reused. You have to create a new instance every time you want to run one.


You can never execute a thread again, not in Java, not in any other language, once the thread is done with the run() method, you cannot restart it, which is why you are getting the IllegalStateException.

You can however still call the methods on that thread but they will run on the thread that is calling them NOT on a different thread. Therefore you will have to create a new one.


You cannot run same instance of an AsyncTask more than once. Let's assume you have an AsyncTask named MyAsyncTaks and you intend to do something like this,

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

The reason for this is, a thread once finishes its 'run' method, cannot be assigned another task. Here, on the first invocation of execute(), your AsyncTask started running and after doing its job, the thread comes out of run. Naturally, next invocation of execute() will throw you exception.

The simplest way to run this more than once is to create a new instance of MyAsyncTaks and call execute on that.

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

Though its not needed to be mentioned here, one must be aware that post Android SDK version Honeycomb, if your run more than one AsyncTask at once, they actually run sequentially. If you want to run them parallally, use executeOnExecutor instead.


Just make a new call like new asyncTask().execute(); You must create a new object to restart that task.


I just create the asynctask then create a runnable that creates new instances of the asynctask. Then you can submit your runnable over and over again to the handler.

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

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


This solved my problem:

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


You can do it like this :

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

and then you can use it :

createAsyncTask().execute();

this make a new instance of your background task everytime.


Async tsk only run once as the Exceptions says the task has already been executed.. So you just have to make a new instance of async and then call .execute(); in order to run it again .. thank you


I created an Arraylist of type ProgressUpdater(Name of class which extends AsyncTask) and added the instances into it(in the onClick of a button). So you can execute and cancel these task when needed.

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

}

}


in your MainActivity you can put so this:

LeoAsyncTask leoAsyncTaskGeneric;


public void onClick_AsyncTask(View view) {

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

    leoAsyncTaskGeneric=leoAsyncTaskInner; 

}

/**if you create a space in memory of your AsyncTask class as a generic, then you can create an instance of that same class within the onClick method, and there the equals, so every time you press onClick you will be using a new instance of the Class AsyncTask, it will not give you problems */


You could cancel your asyncTask when you press the button and then execute it again.

Inside OnClic method:

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


@coder_For_Life22 I think am late for the answer ,anyway you can do like

    @Override
    protected void onPostExecute(Void a) {

        myAsyncTask=new MyAsyncTask();
    }

in order to start a new AsyncTask after execution :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜