我有一种从互联网下载图像并将其存储在位图上的方法。在下载图像时,它会显示一个加载对话框。该方法工作正常,但我想在我的应用程序中添加功能以停止线程(因此停止下载)并在用户按下手机上的后退键时关闭对话框。
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");
}
}
答案 0 :(得分:6)
答案 1 :(得分:1)
关于在活动中管理异步任务的一般建议。
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);
}
答案 2 :(得分: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(...)
}
}
喔。缺少的一点......然后你需要覆盖活动的onBackPressed,或者活动的onStop方法来插入取消线程的代码:imageThread.interrupt();