3

我有一种从互联网下载图像并将其存储在位图上的方法。在下载图像时,它会显示一个加载对话框。该方法工作正常,但我想将功能添加到我的应用程序中以停止线程(因此停止下载)并在用户按下手机上的返回键时关闭对话框。

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();
    }

当用户在我的活动上按后退键时,如何添加停止线程的功能?我在谷歌上找不到路

编辑:这是我尝试使用 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");
        }
    }
4

3 回答 3

6
  1. 你应该使用AsyncTask

  2. 要停止它,您应该使用生命周期方法,Activity例如.onStop()onDestroy()cancel()AsyncTask

  3. 为了不重新发明轮子,您可能应该使用一些可以做到这一点(加载远程图像)的库,例如Ignition

于 2012-10-17T20:14:01.153 回答
1

关于在活动中管理 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);
}
于 2012-10-18T08:03:24.653 回答
0

由于大部分长时间的工作都是通过一次调用完成的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();

于 2012-10-17T20:13:00.320 回答