Отмена текущего соединения при нажатии пользователем

90
9

Я искал об этом, но я не нашел свой конкретный вопрос. Я понимаю, что AskyncTask можно отменить с помощью .cancel(true), но это произойдет, только если у меня есть цикл, в котором я могу проверить значение isCanceled().


Но мой вопрос здесь: как я могу отменить AsyncTask (который застрял в httpclient.execute()), когда пользователь нажимает назад? Если пользователь переходит от этой операции и переходит к другому, я не хочу, чтобы выполнялось неконтролируемое число запусков AsyncTask, так как это может привести к проблемам с памятью, пользователь может перемещаться вперед и назад и создавать неопределенное количество задач. Вот почему я хочу их закрыть. Кто-нибудь знает дорогу? Я отправляю код, который я использую для подключения:


public class Test extends Activity {

@Override
protected void onStart() {
super.onStart();

new ConnectionTask().execute("https://www.mywebserver.com/webservice.php?param1=test");
}

private class ConnectionTask extends AsyncTask<String, Void, String>{

@Override
protected String doInBackground(String... params) {
try {

HttpClient httpclient = DefaultHttpClient(params,clientConnectionManager);
HttpPost httpPost = new HttpPost(params[0]);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();

if(httpEntity != null)
return EntityUtils.toString(httpEntity);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

}

}


Знаете ли вы, что я должен добавить в onStop(), чтобы отменить текущую функцию httpClient.execute()? Иногда застрял почти навсегда.


Я был бы очень признателен за вашу помощь, большое спасибо заранее.


UPDATE


Если я закрою ConnectionManager, я должен снова выполнить квитирование для https, верно? Посмотрите на этот код, когда я создаю httpClient, я использую его для https:


HttpClient httpclient = DefaultHttpClient(params,clientConnectionManager);

Благодарим всех за ваши быстрые ответы и разнообразие предлагаемых здесь решений. Я попытаюсь использовать таймауты (для того, чтобы не ждать слишком много) + функцию cancel(), чтобы избежать обработки onPostExecute. Я скажу, ожидаются ли результаты! Большое вам спасибо!

спросил(а) 2011-09-12T19:51:00+04:00 9 лет назад
1
Решение
56

В классе AsyncTask существует метод cancel(). Поддержание члена в asynctask и отмена его в onDestroy()., затем установите член в null.


Update


Используйте ClientConnectionManager для выключения подключения.


http://developer.android.com/reference/org/apache/http/conn/ClientConnectionManager.html

Обновление 2


Установите эту ссылку для установки таймаута для вашего соединения.


Как установить тайм-аут HttpResponse для Android в Java

ответил(а) 2011-09-12T19:58:00+04:00 9 лет назад
90

согласно Документы HttpClient, используйте HttpUriRequest#abort() для отмены запроса

1,4. Отмена запросов

В некоторых ситуациях выполнение запроса HTTP не может завершиться в течение ожидаемого временного интервала из-за высокой нагрузки на целевом сервере или слишком большого количества одновременных запросов, выпущенных на стороне клиента. В таких случаях может потребоваться преждевременное прекращение запроса и разблокирование исполнительного потока, заблокированного в операции ввода-вывода. HTTP-запросы, выполняемые HttpClient, могут быть прерваны на любом этапе выполнения, вызвав метод HttpUriRequest # abort(). Этот метод является потокобезопасным и может быть вызван из любого потока. Когда HTTP-запрос прерывается, его поток выполнения, даже если он заблокирован в операции ввода-вывода, гарантированно разблокируется, выбирая InterruptedIOException


ответил(а) 2012-06-27T13:30:00+04:00 8 лет, 3 месяца назад
57

Мое понимание заключается в том, что httpClient.execute() блокирует, поэтому нет кода для проверки значения isCancelled(). И вы не хотите закрывать диспетчер подключений.


Это может быть немного взломанным, но вместо каких-либо лучших решений, что произойдет, если вы вызываете Thread.interrupt() в потоке, а httpClient.execute() блокируется?


Быстрый тест может подтвердить это, просто добавьте приватную переменную экземпляра типа Thread внутри вашего определения ConnectionTask, установите ее в Thread.currentThread() вверху doBackground() и добавьте общедоступный метод, который вызывает .interrupt() на нем.


Если вам повезет, это приведет к тому, что httpClient.execute() немедленно выйдет, выбросив исключение. Вы можете поймать это и сделать все, что вам нужно, прежде чем вызов метода закончится, и AsyncTask закончится естественным образом.

ответил(а) 2011-09-12T20:35:00+04:00 9 лет назад
41

Хорошо, есть быстрое решение этой проблемы, которое я использовал в своем случае. Это может быть не так, как если бы вы вернули приложение, оно немедленно ответит, но в фоновом режиме сеть продолжит работу (до тех пор, пока не будет установлен тайм-аут), не блокируя приложение: -


Все операции с сетью в новой службе говорят NSERV. Сделайте NSERV расширением класса Thread и выполните все операции с сетью в методе run. Для большей ясности в коде лучше активировать деятельность/службу, запускающую NSERV, также расширить класс Thread и запустить NSERV из их метода запуска.


Затем используйте статические поля или singleton для доступа к переменным в активности/службе из NSERV.


EX:


public class NSERV  extends Service implements Runnable{
public int onStartCommand (Intent intent, int flags, int startId)
{
Thread t = new Thread (this, "abc");
t.start();
return super.onStartCommand(intent, flags, startId);
}

public void run()
{
//NETWORK OPERATION...
onDestroy();
}

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

ответил(а) 2012-07-07T08:42:00+04:00 8 лет, 2 месяца назад
41

В onPause() или onBackButtonPressed() вызовите cancel() в своей задаче. В doInBackground() сразу после


HttpResponse httpResponse = httpClient.execute(httpPost);

Отметьте isCanceled() и немедленно верните, если true.


Конечно, у вас все еще есть риск запуска нескольких задач, но поскольку эта операция управляется пользовательским интерфейсом (это задача, запускаемая пользовательскими взаимодействиями), должно быть не более двух из них одновременно, при условии, что тайм-аут на HttpClient является разумным.


Update


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


Это должно закрыть сокеты и вызвать немедленное возвращение из execute(). Диспетчер подключений устанавливается при создании DefaultHttpClient.

ответил(а) 2011-09-12T20:04:00+04:00 9 лет назад
41

Вы можете переопределить


onPause() метод активности и напишите там код останова. Если этот параметр определен для кнопки "Назад", вы можете переопределить


onBackButtonPressed(), чтобы остановить выполнение.

ответил(а) 2011-09-12T19:57:00+04:00 9 лет назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема