2

ПроблемаКак остановить выполнение HttpConnection.getInputStream()?

Я бегу метод HttpsUrlConnection.getInputStream() внутри AsyncTask.doInBackground(), который работает от DialogFragment.

Я хочу, чтобы он завершился, когда пользователь вышел из фрагмента.

Если я этого не сделаю, бесполезные данные будут продолжать загружаться в фоновом режиме.

То, что я пытался

Я попытался установить URLConnection объект null в onDismiss() обратного вызова, но это не останавливает метод getInputStream() от выполнения. Я не могу назвать mConnection.disconnect() в потоке пользовательского интерфейса, и это было бы неэффективно в другой AsyncTask, так как они выполняются последовательно.

AsyncTask.cancel() не полезен, так как он не остановит метод doInBackground().

Вопрос

Как заставить возврат из метода getInputStream()?


Код

По желанию @CarlosRobles, вот код моего doInBackground()

URL url = new URL(urlString); 
    setCurrentConnection((HttpsURLConnection) url.openConnection()); 
    mCurrentConnection.setSSLSocketFactory(mSSLSocketFactory); 
    mCurrentConnection.connect(); 

    int responseCode = mCurrentConnection.getResponseCode(); 
    if (responseCode >= 400) { 
     throw new IOException("Bad response code"); 
    } 
    Log.d(TAG, "response code: " + responseCode); 

    // TODO: Should call .close() if IOException happens here? 
    InputStream inputStream = mCurrentConnection.getInputStream(); 

    String response = convertStreamToString(inputStream); 

    inputStream.close(); 
    mCurrentConnection.disconnect(); 

    return response; 

Другие соображения

Я только что проверилвремя выполнения всей функции, указанной в приведенном выше фрагменте, и я только что нашел, что UrlConnection.getResponseCode(), на сегодняшний день является функцией, использующей больше всего времени для запуска. Полагаю, это связано с призывом к UrlConnection.getInputStream() внутри него. Позже, inputStream всегда кэшируется в объект соединения, поэтому UrlConnection.getInputstream() почти не занимает время в моей функции.

+0

Как насчет вызова вручную 'mTask = new YourAsyncTask(). Execute(); mTask.cancel (true); ' – Elshan

+0

Взгляните на [RoboSpice] (https://github.com/octo-online/robospice). У них есть хорошая модель для обработки прекращенных действий. Возможно, вы можете скопировать некоторые идеи оттуда. И вам не нужно вызывать mConnection.disconnect из UI-Thread. Просто установите флаг volatile и отметьте этот флаг в логике загрузки. – hgoebl

+0

@ Elshan Я уже это делаю. Это неэффективно, прочитайте вопрос. – doplumi

ответ

1

Из пользовательского интерфейса можно назвать AsyncTask.cancel(true); и в doInBackground() вы можете держать вызова isCancelled(), чтобы обнаружить, если функция должна прервать, после того, что вы можете делать все, что вам нужно

Как мы можем читать here

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

в вашем doInBackground у вас есть функция convertStreamToString функция. Это самая длинная операция, и внутри ее наверняка вы можете прервать загрузку. Для использования внутри него у вас есть какой-то цикл для извлечения содержимого потока и сохранения его в строку, и там вы можете прервать его.

private void convertStreamToString() {  


      //.. 


      //loop to convert StreamToString 
      { 
       //.. 

       // Escape early if cancel() is called 
      if (isCancelled()) { 
       mConnection.disconnect() 
       break; 
      } 
      } 

    } 
+0

У меня нет цикла, запущенного в моей onBackground(), так как я упоминал в своем ответе, я не могу использовать 'AsyncTask.cancel()'. Возможно, у вас есть идея о том, как использовать его в сочетании с 'HttpsUrlConnection.getInputStream()'? Это было бы мило. – doplumi

+0

, но getInputStream не так много времени, что просто получает входной поток, и я предполагаю, что после этого где-то вы читаете поток, и это может быть сделано в цикле и может быть прервано. Можете ли вы вставить код AsyncTask? –

+0

Я просто запустил соединение и прочитал поток. Я редактировал вопрос, чтобы вы могли видеть код. – doplumi

Смежные вопросы