2015-06-01 2 views
0

У меня есть класс, который представляет собой блок задач загрузки.Как правильно остановить поток?

import android.os.Environment; 
import android.util.Log; 

import java.io.BufferedInputStream; 
import java.io.FileOutputStream; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.OutputStream; 
import java.net.URL; 
import java.net.URLConnection; 

/** 
* Created by Sergey Shustikov ([email protected]) at 2015. 
*/ 
public class DownloadTask extends Thread implements DownloadActions 
{ 

    private DownloadStateListener mListener; 
    private String mDownloadLink; 

    public DownloadTask(String downloadLink) 
    { 
     mDownloadLink = downloadLink; 
    } 

    @Override 
    public void cancel() 
    { 
     interrupt(); 
     mListener.onDownloadCanceled(mDownloadLink); 
    } 

    @Override 
    public void setDownloadStateChangedListener(DownloadStateListener listener) 
    { 
     mListener = listener; 
    } 

    @Override 
    public void run() 
    { 
     int count; 
     try { 
      mListener.onDownloadStarted(mDownloadLink); 
      URL url = new URL(mDownloadLink); 
      URLConnection connection = url.openConnection(); 
      connection.connect(); 

      // this will be useful so that you can show a tipical 0-100% 
      // progress bar 
      int contentLength = connection.getContentLength(); 

      // download the file 
      InputStream input = new BufferedInputStream(connection.getInputStream()); 

      // Output stream 
      OutputStream output = new FileOutputStream(Environment.getExternalStorageDirectory().toString() + "/Download/"); 

      byte data[] = new byte[1024]; 

      long total = 0; 

      while ((count = input.read(data)) != -1) { 
       total += count; 
       // publishing the progress.... 
       // After this onProgressUpdate will be called 
       mListener.onDownloadProgress(mDownloadLink, (int) ((total * 100)/contentLength)); 

       // writing data to file 
       output.write(data, 0, count); 
      } 

      close(connection, input, output); 
      mListener.onDownloadFinished(mDownloadLink); 

     } catch (Exception e) { 
      Log.e("Error: ", e.getMessage()); 
      mListener.onDownloadFailed(mDownloadLink, new DownloadError(e.getMessage())); 
     } 

    } 

    private synchronized void close(URLConnection connection, InputStream input, OutputStream output) 
    { 
     try { 
      // flushing output 
      if (output != null) { 
       output.flush(); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 

     // closing streams 
     try { 
      // flushing output 
      if (output != null) { 
       output.close(); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     try { 
      // flushing output 
      if (input != null) { 
       input.close(); 
      } 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

мне нужно остановить загрузку, четкие загруженные данные и закрыть соединение, когда я называю cancel() метод.

Я знаю - в Java много дискуссий о механизме остановки.

я не могу использовать this answer:

Вы можете создать логическое поле и проверить его в перспективе:

public class Task implements Runnable { 

    private volatile boolean isRunning = true; 

    public void run() { 

     while (isRunning) { 
     //do work 
     } 
    } 
    public void kill() { 
     isRunning = false; 
    } 

} 

Чтобы остановить его просто называют

task.kill(); 

Это должно Работа.

потому что это не операция в петле.

Так как я могу это сделать правильно?

+1

*, потому что нет работы в цикле .* что это значит? – Blackbelt

+0

несколько указателей на то, что можно прервать: http://stackoverflow.com/questions/19380576/interruptible-network-i-o-in-java – njzk2

ответ

1

Вы косяк прервать поток, если код, который вы не позволить нить пробег прерывает - то есть - проверка на себя, если это было прерываться.

EDIT В вашем случае - что-то вроде:

final Thread cancelable = new Thread() { 

      @Override 
      public void run() { 
       int count; 
       try { 
        ... 

        while ((count = input.read(data)) != -1 && !Thread.interrupted()) { 
         total += count; 
         // publishing the progress.... 
         // After this onProgressUpdate will be called 
         mListener.onDownloadProgress(mDownloadLink, (int) ((total * 100)/contentLength)); 

         // writing data to file 
         output.write(data, 0, count); 
        } 
        if (Thread.interrupted()) { 
         mListener.onDownloadCanceled(mDownloadLink); 
        } 
        ... 
       } 
      } 
      } 
     }); 

и остановить загрузку вы должны вызвать:

cancelable.interrupt(); 
+0

Хорошо. Я принимаю ваше предположение. Но как это правильно отображается в коде? Как я могу правильно остановить задачу в моем случае? –

+0

@SergeyShustikov есть –

+1

спасибо. Я принимаю это. –

2

Вы должны прервать (потенциально длительный) процесс чтения:

while ((count = input.read(data)) != -1 && isRunning) { 
    // perform reading 
} 
+0

Я думаю, что это не очень хорошая идея. Я могу отменить задачу, когда цикл завершения кода. Например, в методе 'out.close()'. –

+0

@SergeyShustikov вы можете сделать это после цикла while ... Так же, как вы это делаете. Этот ответ делает то, о чем вы просите. – Balduz

+0

Balduz, я понимаю, что мне нужно делать. Вы предлагаете мне проверять везде с помощью выражения 'boolean' (после каждой строки для лучшего), но это хорошая практика? –

0
public class Task implements Runnable { 

    private boolean cancel; 

    public void run() { 

    try{ 

     while (yourCondition) { 
     //do work 
      if(cancel){ 
      throw new DownloadCancelException(); 
      } 
     } 
    }catch(DownloadCancelException e){ 
     //clear downloaded stuff over here 
    } 

    } 
    public void kill() { 
     cancel = true; 
    } 

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