Подтвердить что ты не робот

Как запустить одну и ту же асинтету более одного раза?

У меня запускается 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)

Можно ли запустить это дважды?

4b9b3361

Ответ 1

Просто создайте другой экземпляр и выполните его.

Ответ 2

Как и потоки, AsyncTask нельзя использовать повторно. Вы должны создать новый экземпляр каждый раз, когда хотите его запустить.

Ответ 3

Вы никогда не сможете выполнить поток снова, а не в Java, а не на каком-либо другом языке, как только поток выполняется с помощью метода run(), его нельзя перезапустить, поэтому вы получаете IllegalStateException,

Однако вы все равно можете вызвать методы в этом потоке, но они будут выполняться в потоке, который вызывает их NOT в другом потоке. Поэтому вам нужно будет создать новый.

Ответ 4

Вы не можете запускать один и тот же экземпляр AsyncTask более одного раза. Предположим, у вас есть AsyncTask с именем MyAsyncTaks, и вы намерены сделать что-то вроде этого,

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

Причиной этого является то, что нить, однажды закончившая свой метод "run", не может быть назначена другой задаче. Здесь, при первом вызове execute(), ваш AsyncTask начал работать и после выполнения своей работы поток выходит из строя. Естественно, что следующий вызов execute() вызовет вам исключение.

Самый простой способ запускать это более одного раза - создать новый экземпляр MyAsyncTaks и выполнить его выполнение.

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

Хотя его не нужно упоминать здесь, нужно помнить, что после Android SDK версии Honeycomb, если вы запускаете сразу несколько Асинхронных задач, они фактически запускаются последовательно. Если вы хотите запустить их параллально, вместо этого используйте executeOnExecutor.

Ответ 5

Просто создайте новый вызов, как новый asyncTask(). execute(); Вы должны создать новый объект для перезапуска этой задачи.

Ответ 6

Я просто создаю asynctask, а затем создаю runnable, который создает новые экземпляры asynctask. Затем вы можете снова и снова пересылать ваш runnable в обработчик.

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

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

Ответ 7

Вы можете сделать это так:

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

а затем вы можете использовать его:

createAsyncTask().execute();

это делает новый экземпляр вашей фоновой задачи каждый раз.

Ответ 8

Я создал Arraylist типа ProgressUpdater (имя класса, который расширяет 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]);
    }

}

}

Ответ 9

в вашем MainActivity вы можете сделать так:

LeoAsyncTask leoAsyncTaskGeneric;


public void onClick_AsyncTask(View view) {

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

    leoAsyncTaskGeneric=leoAsyncTaskInner; 

}

/**, если вы создаете пространство в памяти вашего класса AsyncTask в качестве общего, тогда вы можете создать экземпляр того же класса в методе onClick, и там равны, поэтому каждый раз, когда вы нажимаете onClick, вы будете используя новый экземпляр класса AsyncTask, он не даст вам проблем   */

Ответ 10

Вы можете отменить асинхронную задачу, нажав кнопку и затем выполнить ее снова.

Внутри OnClic метод:

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

Ответ 11

Это решило мою проблему:

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

Ответ 12

@coder_For_Life22 Я думаю, что опоздал на ответ, в любом случае вы можете сделать как

    @Override
    protected void onPostExecute(Void a) {

        myAsyncTask=new MyAsyncTask();
    }

для запуска новой AsyncTask после выполнения :)

Ответ 13

Правила потоков

  • Класс AsyncTask должен быть загружен в поток пользовательского интерфейса. Это делается автоматически с JELLY_BEAN.
  • Экземпляр задачи должен быть создан в потоке пользовательского интерфейса. execute (Params...) должен быть вызван в потоке пользовательского интерфейса.
  • Не вызывайте onPreExecute(), onPostExecute (Result), doInBackground (Params...), onProgressUpdate (Progress...) вручную.
  • Задача может быть выполнена только один раз (исключение будет выдано, если будет предпринята вторая попытка).

Для более подробной информации, пожалуйста, войдите в эту ссылку