Предотвращать выполнение асинтезы несколько раз

Я вызываю asynctask из моего потока пользовательского интерфейса нажатием кнопки, которая выполняет некоторые запросы HTTP-Get.

Что произойдет, если пользователь снова нажмет кнопку до завершения текущей задачи? Является ли это внутренне обработанной асинтексом или мне нужно самому позаботиться об этом?

Есть два способа сделать это.

1: Показать диалог выполнения и заблокировать пользователя для дальнейшего ввода.

2: Создайте переменную AsyncTask в закрытой области. Тогда это никогда не будет работать более одного раза.

Почему бы не использовать булевский флаг и проверить его состояние? Я использую эту логику в своих бесконечных списках и никогда не работал.

Переключить флаг в doInBackground()

 @Override protected Void doInBackground(Void... params) { loadingData = true; } 

И снова в onPostExecute()

 @Override protected void onPostExecute(Void result) { // CHANGE THE LOADINGMORE STATUS TO PERMIT FETCHING MORE DATA loadingData = false; } 

И для прослушивателя кликов кнопки

 your_btn.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { if (loadingData == false) { // RUN THE ASYNCTASK AGAIN } else if (loadingData == true) { // SHOW A TOAST THAT YOU ARE ALREADY FETCHING DATA } } }); 

Вы можете вызвать getStatus() в вашей AsyncTask чтобы проверить, запущен ли он и не запускает ли кнопка щелчка в этом случае.

Для этого вам определенно нужно сохранить экземпляр AsyncTask где-нибудь и получить к нему доступ.

Будет вызвана другая AsyncTask, которая, вероятно, вызовет у вас трудности – условия гонки с сохранением данных, если вы ее сохраняете и т. Д. Я бы рекомендовал отключить кнопку при получении события onClick и отобразить счетчик некоторого описания, указывающий, что что-то происходит в фон.

Мы достигли чего-то подобного с кнопкой обновления, помещенной в панель действий. Обратите внимание, что наша задача async выполняется под приложением app.Service поэтому во время изменения конфигурации (где hasStartedSync получает перезапуск) мы полагаемся на проверку «isTheSyncServiceRunning».

 // on setting the selection buttons up public void onPrepareOptionsMenu(final Menu menu) { super.onPrepareOptionsMenu(menu); final MenuItem refreshItem = menu.findItem(id.sync); if (isSynchronisationServiceRunning() || hasStartedSync) { refreshItem.setEnabled(false); if (Build.VERSION.SDK_INT > 10) { // Replace the refresh icon with an indeterminate spinner for > 10 API. final LayoutInflater inflater = (LayoutInflater)getSherlockActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE); refreshItem.setActionView(inflater.inflate(layout.actionbar_indeterminate_progress, null)); } } else { refreshItem.setEnabled(true); refreshItem.setActionView(null); } } // on selection. public boolean onOptionsItemSelected(final MenuItem item) { boolean isSelected; switch (item.getItemId()) { case id.sync: // Fire request to start GET here. hasStartedSync = true; invalidateOptionsMenu(); break; ... 

Два пути:

  1. В onPreExeccute() AsyncTask показан ProgressDialog с его setCancelable(false) . В onPostExecute() для AsyncTask вызывают dismiss() на ProgressDialog. Появится диалоговое окно блокировки. Вы также можете показать сообщение или прогресс здесь.

  2. В onPreExeccute() AsyncTask вызовите setEnabled(false) на Button. В onPostExecute() для AsyncTask вызывается setEnabled(true) на Button. Это отключит кнопку до тех пор, пока задача будет запущена. Вы также можете изменить текст кнопки в этих точках. Или даже временно замените его счетчиком хода (например, в ActionBar).

Кроме того, вы можете переключаться между кнопками «run» и «cancel», как кнопка обновления в современных веб-браузерах. Это даст больший контроль над пользователем.

onDoInBackground() все внутри onDoInBackground() в try-catch , так что AsyncTask всегда выйдет нормально, и onPostExecute() всегда вызывается. Вы можете судить по параметру результата onPostExecute(result) , получил ли HTTP-запрос что-либо или нет.

Пример: просто вызовите этот метод для загрузки некоторого текста в TextView с сервера при нажатии Button :

 public static void runHTTP(final TextView targetView, final Button triggerBtn){ //---new task---- AsyncTask<Void,Void,String> task = new AsyncTask<Void, Void, String>(){ @Override protected void onPreExecute() { super.onPreExecute(); //----disable button--- triggerBtn.setEnabled(false); //---show message---- targetView.setText("Loading..."); } @Override protected void onPostExecute(String result) { super.onPostExecute(result); //----update result--- targetView.setText(result); //----re-enable button--- triggerBtn.setEnabled(true); } @Override protected String doInBackground(Void... voids) { //---default value-- String result = "No Data"; //--for safety-- try{ //-----do time consuming stuff here --- }catch (Exception e){ //---error value-- result = "Error fetching data"; } return result; } }; //----run task---- task.execute(); }