Как отменить процесс выполнения DefaulHttpClient в многопоточности - PullRequest
1 голос
/ 10 августа 2011

Я занимаюсь разработкой приложения для Android, которое в значительной степени зависит от Интернета, я часто получаю данные с помощью этого RestClient Class , в котором подробно описывается использование DefaultHttpClient для выполнения сетевых запросов.

И я всегда использую другой поток для выполнения HTTP-запроса, я создаю такой класс:

public class AsyncWorker {

    final String SERVER_URL = "http://api.blabla.com";
    RestClient client = new RestClient();

    public void requestHttp(final String url, final ArrayList<NameValuePair> params, final RequestListener listener) {
        new Thread(new Runnable() {

            public void run() {
                try {
                    client.setUrl(url);
                    client.setParams(params);
                    client.Execute(RestClient.RequestMethod.POST);
                    String response = client.getResponse();
                    listener.onComplete(response);
                } catch (Exception ex) {
                    Log.d("LOGIN", ex.getMessage());
                }
            }
        }).start();
    }
    etc...

Поэтому, когда мне нужно выполнить HTTP-запрос, мне нужно только создать объект AsyncWorker и предоставить интерфейс обратного вызова RequestListener.

Но проблема в том, как я могу отменить HTTP-запрос, когда пользователь нажимает кнопку назад / отмена ? и в этом случае приложение все еще находится в одном действии, например, я создаю диалоговое окно, и пользователь делает запрос из этого диалогового окна, а затем нажимает кнопку возврата, диалоговое окно закрывается, и мне нужно отменить запрос в это время.

Ответы [ 4 ]

3 голосов
/ 20 февраля 2014

У меня была та же проблема, и я смог найти решение. Вот что я сделал:

Я использовал CloseableHttpClient вместе с другими связанными классами вместо DefaultHttpClient , который по умолчанию поставляется с Android.

Эти классы из https://hc.apache.org/downloads.cgi. ИЛИ для прямого доступа: http://apache.mirrors.hoobly.com//httpcomponents/httpclient/binary/httpcomponents-client-4.3.2-bin.tar.gz

При этом вызов метода abort () для объекта Request фактически прервет соединение. Однако использование этой библиотеки не является решением; Причина в том, что Android уже имеет устаревшую библиотеку HTTPCLIENT, и большинство классов в библиотеке, на которые указывает вышеуказанная ссылка, могут отсутствовать во время выполнения.

Проблема заключается в том, что и пакеты в вышеупомянутой библиотеке, и встроенный пакет httpclient org.apache имеют одинаковое пространство имен, что приведет к использованию только встроенных классов org.apache, предоставляемых Android при компиляции.

Пример этой проблемы можно найти здесь: java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INSTANCE .

Спасибо ребятам, которые предоставили http://code.google.com/p/httpclientandroidlib/ в качестве опции (находится в разделе ответов java.lang.NoSuchFieldError: org.apache.http.message.BasicLineFormatter.INSTANCE )

Рекомендация : одно место для фактической отмены http-запроса может быть в OnCancel Listener диалогового окна хода выполнения вместо метода обратного вызова AyncTask onCancelled ().

1 голос
/ 12 августа 2011

Используемый вами объект RestClient не предоставляет ни одного interrupt() метода DefaultHttpClient (который является вспомогательным объектом, выполняющим большую часть работы).Не проблема - DefaultHttpClient, похоже, не имеет никаких функций прерывания или прерывания, которые можно было бы открыть в первую очередь.

Итак, слева от вас есть операция блокировки на client.Execute().

Вашна полпути к решению - поместить блокировку в поток.Где ваше падение - ваша архитектура - вы используете настройку Thread / Listener, которая не дает вам много места для маневра.

Попробуйте переключить свой анонимный Thread на AsyncTask.Это не решит проблему блокирования client.Execute(), но позволит вам выбросить слушателя (заменив его на onProgressUpdate() или onPostExecute()).

То, что это сделает, позволит вам позвонить task.cancel(), сигнализируя Задаче, что она больше не нужна.Это позволит вам переназначить новый AsyncTask, осиротев от отмененной задачи, потерянный поток затем быстро завершит свою работу и тихо умрет, в то время как остальная часть вашего приложения выполнит то, что ему нужно.

((На несвязанном примечании «Execute ()» является методом и не должен быть написан заглавными буквами))

0 голосов
/ 10 августа 2011

Предлагаю вам взглянуть на интерфейс ClientConnectionManager.Это позволяет вам делать такие вещи, как освобождение соединения, закрытие соединения и т. Д. Однако вам может потребоваться улучшить реализацию RestClient, поскольку ваш RestClient не предоставляет базовый объект DefaultHttpClient (из которого вы можете получитьна ClientConnectionManager с использованием метода getClientConnectionManager()).

0 голосов
/ 10 августа 2011

Используйте потоковые примитивы. Установите флаг running и установите его на true изначально. Делайте ваши REST-запросы в цикле while(running).

В вашем onPause() установите флаг запуска на false.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...