Можно остановить поток, когда пользователь нажмет клавишу?

У меня есть метод, который загружает изображение из Интернета и сохраняет его на растровом изображении. Пока он загружает изображение, он показывает диалог загрузки. Метод работает нормально, но я хочу добавить функциональность в свое приложение, чтобы остановить поток (так что прекратите загрузку) и отпустите диалог, если пользователь нажмет на клавиатуре обратно клавишу.

public static void getRemoteImage(final String url, final Handler handler) { Thread thread = new Thread(){ public void run() { try { Looper.prepare(); handler.sendEmptyMessage(Util.SHOW_LOADING_DIALOG); final URL aURL = new URL(url); final URLConnection conn = aURL.openConnection(); conn.connect(); final BufferedInputStream bis = new BufferedInputStream(conn.getInputStream()); image = BitmapFactory.decodeStream(bis); bis.close(); handler.sendEmptyMessage(Util.HIDE_LOADING_DIALOG); Looper.loop(); }catch (Exception e) {e.printStackTrace();} } }; thread.start(); } 

Как я могу добавить функциональность, чтобы остановить поток, когда пользователь нажимает клавишу «Назад» в моей активности? Я не могу найти путь в Google

EDIT: это моя попытка использовать Ovidiu ответ, но это не работает 🙁

 @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK) { dialogHandler.sendEmptyMessage(Util.HIDE_DIALOG); task.cancel(true); return true; } return super.onKeyDown(keyCode, event); } private class DownloadTask extends AsyncTask{ @Override protected void onPreExecute() { super.onPreExecute(); //INITIALIZATIONS } @Override protected Object doInBackground(Object... params) { try { dialogHandler.sendEmptyMessage(Util.SHOW_DIALOG); final URL aURL = new URL(url); final URLConnection conn = aURL.openConnection(); conn.connect(); final BufferedInputStream bis = new BufferedInputStream(conn.getInputStream()); image = BitmapFactory.decodeStream(bis); bis.close(); dialogHandler.sendEmptyMessage(Util.HIDE_DIALOG); }catch (Exception e) {e.printStackTrace();} return null; } @Override protected void onCancelled(){ super.onCancelled(); System.out.println("Task cancelled"); } } 

  1. Вы должны использовать AsyncTask

  2. Чтобы остановить его, вы должны использовать методы жизненного цикла Activity такие как onStop() или onDestroy() для cancel() AsyncTask .

  3. Чтобы не изобретать велосипед, вы, вероятно, должны использовать некоторые библиотеки, которые точно соответствуют (загружать удаленные изображения), например Ignition .

Общая рекомендация об управлении AsyncTask в рамках действия.

 public class MyActivity extends Activity { // Restore the task we kept alive public void onCreate(Bundle savedInstanceState) { myTask = (MyTask) getLastNonConfigurationInstance(); if (myTask!=null) myTask.connect(this); } // Keep the task alive on screen rotation for example public Object onRetainNonConfigurationInstance() { myTask.disconnect(); return myTask; } // Kill the task when we stop. If you wanna keep the task alive, you don't kill it here. protected void onStop() { killTask(); super.onStop(); } // Disconnect the task from this activity and cancel it if needed private void killTask() { if (myTask!=null) { myTask.cancel(true); myTask.disconnect(); myTask = null; } } // Kill task if running, create new one, link it to us and run it private void launchTask() { killTask(); myTask = new MyTask(); myTask.connect(this).execute(); } void handleTaskCancelled() { Toast.makeText(this, "Task cancelled", Toast.LENGTH_SHORT).show(); } void handleTaskCompleted(String result) { Toast.makeText(this, "Task done: " + result, Toast.LENGTH_SHORT).show(); } private MyTask myTask; } 

// Либо автономный класс, либо статический внутренний класс вашей деятельности

 public class MyTask extends AsyncTask<Void, Void, String> { @Override protected void onPostExecute(String result){ if (activityRef.get()!=null) { activityRef.get().handleTaskCompleted(result); } } @Override protected void onCancelled(){ if (activityRef.get()!=null) { activityRef.get().handleTaskCancelled(); } } public MyTask connect(MyActivity a) { activityRef = new WeakReference<MyActivity>(a); } public void disconnect() { activityRef.clear(); } // Never keep a strong reference to an activity, you might leak memory WeakReference<MyActivity> activityRef = new WeakReference<MyActivity>(null); } 

Поскольку большая часть длительной работы выполняется с помощью одного вызова BitmapFactory.decodeStream(bis); , Вы не сможете реально остановить поток мгновенно в любом случае …

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

 public class ImageThread extends Thread { Bitmap image = null; public void run() { // 1. download the stream to a byte[] while data available in input stream read a few bytes and store them if (isInterrupted()) cleanUpAndExit(); endwhile // 2. Create bitmap from data image = BitmapFactory.decodeByteArray(...) } } 

BitmapFactory.decodeByteArray

Ой. И недостающий бит … Затем вам нужно переопределить onBackPressed активности или метод onStop для включения кода для отмены потока: imageThread.interrupt();