Отменить запрос Jsoup [дублировать]

Интересно, что ни один из ответов на этой странице не упоминает два крайних случая, надеюсь, никто не возражает, если я их добавлю:

Случай с краем # 1: одновременный доступ к Словарю

Родовые словари в .NET не являются потокобезопасными, а иногда могут бросать NullReference или даже (чаще) a KeyNotFoundException при попытке получить доступ к ключу из двух параллельных потоков. Исключение в этом случае является довольно ошибочным.

Случай с краем # 2: небезопасный код

Если код NullReferenceException задан кодом unsafe, вы можете посмотреть на переменные указателя , и проверьте их на IntPtr.Zero или что-то в этом роде. Это одно и то же («исключение нулевого указателя»), но в небезопасном коде переменные часто переводятся в типы значений / массивы и т. Д., И вы ударяете головой о стену, задаваясь вопросом, как тип значения может исключение.

(Еще одна причина для небезопасного использования небезопасного кода, если вам это нужно)

51
задан MScott 12 October 2011 в 01:41
поделиться

8 ответов

НАЙДЕНО РЕШЕНИЕ: Я добавил слушателя действий перед загрузкойDialog.show () следующим образом:

    uploadingDialog.setOnCancelListener(new DialogInterface.OnCancelListener(){
          public void onCancel(DialogInterface dialog) {
              myTask.cancel(true);
              //finish();
          }
    });

Таким образом, когда я нажимаю кнопку «Назад», вышеуказанный OnCancelListener отменяет оба диалога и задачу. Также вы можете добавить финиш (), если вы хотите закончить всю операцию по нажатой клавише. Не забудьте объявить свою задачу async как переменную вроде этого:

    MyAsyncTask myTask=null;

и выполнить вашу задачу async следующим образом:

    myTask = new MyAsyncTask();
    myTask.execute();
30
ответ дан MScott 24 August 2018 в 04:48
поделиться

У меня была аналогичная проблема - по сути, я получал NPE в асинхронной задаче после того, как пользователь уничтожил действие. После изучения проблемы с переполнением стека я принял следующее решение:

volatile boolean running;

public void onActivityCreated (Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    running=true;
    ...
    }


public void onDestroy() {
    super.onDestroy();

    running=false;
    ...
}

Затем я периодически проверяю «если работает» в моем асинхронном коде. Я испытал это, и теперь я не могу «сломать» свою деятельность. Это прекрасно работает и имеет преимущество в том, чтобы быть проще, чем некоторые из решений, которые я видел на SO.

2
ответ дан 4ndrew 24 August 2018 в 04:48
поделиться

Вы можете просто попросить об отмене, но на самом деле не прекратите его. См. Этот ответ .

2
ответ дан Community 24 August 2018 в 04:48
поделиться

создать некоторые переменные-члены в вашей деятельности, такие как

YourAsyncTask mTask;
Dialog mDialog;

использовать их для вашего диалога и задачи;

в onPause () просто вызвать

if(mTask!=null) mTask.cancel(); 
if(mDialog!=null) mDialog.dismiss();
9
ответ дан jkhouw1 24 August 2018 в 04:48
поделиться

Из SDK:

Отмена задачи

Задачу можно отменить в любое время, вызвав cancel (boolean). Вызов этого метода приведет к последующим вызовам isCancelled (), чтобы вернуть true. После вызова этого метода onCancelled (Object) вместо onPostExecute (Object) будет вызываться после того, как doInBackground (Object []) вернется. Чтобы гарантировать, что задача будет отменена как можно быстрее, вы всегда должны проверять возвращаемое значение isCancelled () периодически из doInBackground (Object []), если это возможно (внутри цикла, например.)

Итак, ваш код подходит для прослушивателя диалога:

uploadingDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    public void onCancel(DialogInterface dialog) {
        myTask.cancel(true);
        //finish();
    }
});

Теперь, как я уже упоминал ранее из SDK, вам нужно проверить, отменена ли задача или нет, для этого вам нужно проверить isCancelled () внутри метода onPreExecute ().

Например:

if (isCancelled()) 
    break;
else
{
   // do your work here
}
92
ответ дан moturi manasa 24 August 2018 в 04:48
поделиться

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

private class UpdateLibrary extends AsyncTask<Void, Integer, Boolean>{
    private ProgressDialog dialog = new ProgressDialog(Library.this);
    private int total = Library.instance.appState.getAvailableText().length;
    private int count = 0;

    //Used as handler to cancel task if back button is pressed
    private AsyncTask<Void, Integer, Boolean> updateTask = null;

    @Override
    protected void onPreExecute(){
        updateTask = this;
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        dialog.setOnDismissListener(new OnDismissListener() {               
            @Override
            public void onDismiss(DialogInterface dialog) {
                updateTask.cancel(true);
            }
        });
        dialog.setMessage("Updating Library...");
        dialog.setMax(total);
        dialog.show();
    }

    @Override
    protected Boolean doInBackground(Void... arg0) {
            for (int i = 0; i < appState.getAvailableText().length;i++){
                if(isCancelled()){
                    break;
                }
                //Do your updating stuff here
            }
        }

    @Override
    protected void onProgressUpdate(Integer... progress){
        count += progress[0];
        dialog.setProgress(count);
    }

    @Override
    protected void onPostExecute(Boolean finished){
        dialog.dismiss();
        if (finished)
            DialogHelper.showMessage(Str.TEXT_UPDATELIBRARY, Str.TEXT_UPDATECOMPLETED, Library.instance);
        else 
            DialogHelper.showMessage(Str.TEXT_UPDATELIBRARY,Str.TEXT_NOUPDATE , Library.instance);
    }
}
10
ответ дан odiggity 24 August 2018 в 04:48
поделиться

Я хотел бы улучшить код. Когда вы нажимаете aSyncTask, автоматически вызывается onCancelled() (метод обратного вызова aSyncTask), и вы можете скрыть свой progressBarDialog.

Вы также можете включить этот код:

public class information extends AsyncTask<String, String, String>
    {
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected String doInBackground(String... arg0) {
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            this.cancel(true);
        }

        @Override
        protected void onProgressUpdate(String... values) {
            super.onProgressUpdate(values);
        }

        @Override
        protected void onCancelled() {
            Toast.makeText(getApplicationContext(), "asynctack cancelled.....", Toast.LENGTH_SHORT).show();
            dialog.hide(); /*hide the progressbar dialog here...*/
            super.onCancelled();
        }

    }
5
ответ дан Rahul Raina 24 August 2018 в 04:48
поделиться

В большинстве случаев, когда я использую AsyncTask, моя бизнес-логика находится в отдельном бизнес-классе, а не в пользовательском интерфейсе. В этом случае у меня не было бы цикла на doInBackground (). Примером может служить процесс синхронизации, который потребляет службы и сохраняет данные один за другим.

В конечном итоге я передаю свою задачу бизнес-объекту, чтобы он мог обрабатывать отмену. Моя настройка такова:

public abstract class MyActivity extends Activity {

    private Task mTask;
    private Business mBusiness;

    public void startTask() {
        if (mTask != null) {
            mTask.cancel(true);
        }
        mTask = new mTask();
        mTask.execute();
    }
}

protected class Task extends AsyncTask<Void, Void, Boolean> {
    @Override
    protected void onCancelled() {
        super.onCancelled();

        mTask.cancel(true);

        // ask if user wants to try again
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        return mBusiness.synchronize(this);
    }

    @Override
    protected void onPostExecute(Boolean result) {
        super.onPostExecute(result);

        mTask = null;

        if (result) {
            // done!
        }
        else {
            // ask if user wants to try again
        }
    }
}

public class Business {
    public boolean synchronize(AsyncTask<?, ?, ?> task) {
        boolean response = false;
        response = loadStuff(task);

        if (response)
            response = loadMoreStuff(task);

        return response;
    }

    private boolean loadStuff(AsyncTask<?, ?, ?> task) {
        if (task != null && task.isCancelled()) return false;

        // load stuff

        return true;
    }
}
3
ответ дан saulobrito 24 August 2018 в 04:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: