Android:取消asynchronous任务
我使用asynchronous任务来上传图像并获得一些结果。
在上传图片时,我看到一个进度对话框,用如下方法写入onExpExcute()方法:
protected void onPreExecute() { uploadingDialog = new ProgressDialog(MyActivity.this); uploadingDialog.setMessage("uploading"); uploadingDialog.setCancelable(true); uploadingDialog.show(); }
好的,当我按下后退button时,显然对话框由于setCancelable(true)而消失。
但是(显然)asynchronous任务并没有停止。
那我该如何解决这个问题? 当我按下后退button时,我想取消对话框和asynchronous任务。 有任何想法吗?
编辑: find解决scheme 。 看到我的答案在下面。
从SDK:
取消任务
任何时候都可以通过调用cancel(boolean)来取消任务。 调用此方法将导致对isCancelled()的后续调用返回true。
调用这个方法之后,onCancelled(Object),而不是onPostExecute(Object)将在doInBackground(Object [])返回后被调用。
为了确保尽快取消任务,应该总是从doInBackground(Object [])中定期检查isCancelled()的返回值,如果可能的话(例如在一个循环内部)。
所以你的代码对话框监听器是正确的:
uploadingDialog.setOnCancelListener(new DialogInterface.OnCancelListener() { public void onCancel(DialogInterface dialog) { myTask.cancel(true); //finish(); } });
现在,正如我前面提到的SDK,你必须检查任务是否被取消,因为你必须在onPreExecute()方法中检查isCancelled() 。
例如:
if (isCancelled()) break; else { // do your work here }
find解决scheme :我在上传Dialog.show()之前添加了一个动作监听器:
uploadingDialog.setOnCancelListener(new DialogInterface.OnCancelListener(){ public void onCancel(DialogInterface dialog) { myTask.cancel(true); //finish(); } });
这样,当我按下后退button,上面的OnCancelListener取消对话框和任务。 如果你想完成整个活动,你也可以添加完成()。 记得把你的asynchronous任务声明为这样的variables:
MyAsyncTask myTask=null;
并像这样执行你的asynchronous任务:
myTask = new MyAsyncTask(); myTask.execute();
我花了一段时间弄清楚了这一点,我只想要一个简单的例子来说明如何去做,所以我想我会怎么做。 这是一些更新库的代码,并有一个进度对话框,显示有多less本书已经更新,并在用户closures对话时取消:
private class UpdateLibrary extends AsyncTask<Void, Integer, Boolean>{ private ProgressDialog dialog = new ProgressDialog(Library.this); private int total = Library.instance.appState.getAvailableText().length; private int count = 0; //Used as handler to cancel task if back button is pressed private AsyncTask<Void, Integer, Boolean> updateTask = null; @Override protected void onPreExecute(){ updateTask = this; dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); dialog.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss(DialogInterface dialog) { updateTask.cancel(true); } }); dialog.setMessage("Updating Library..."); dialog.setMax(total); dialog.show(); } @Override protected Boolean doInBackground(Void... arg0) { for (int i = 0; i < appState.getAvailableText().length;i++){ if(isCancelled()){ break; } //Do your updating stuff here } } @Override protected void onProgressUpdate(Integer... progress){ count += progress[0]; dialog.setProgress(count); } @Override protected void onPostExecute(Boolean finished){ dialog.dismiss(); if (finished) DialogHelper.showMessage(Str.TEXT_UPDATELIBRARY, Str.TEXT_UPDATECOMPLETED, Library.instance); else DialogHelper.showMessage(Str.TEXT_UPDATELIBRARY,Str.TEXT_NOUPDATE , Library.instance); } }
在你的活动中创build一些成员variables
YourAsyncTask mTask; Dialog mDialog;
将这些用于对话和任务;
在onPause()简单地调用
if(mTask!=null) mTask.cancel(); if(mDialog!=null) mDialog.dismiss();
我想改进代码。 当你使用aSyncTask时,会自动调用aSyncTask
onCancelled()
( aSyncTask
的callback方法),在那里你可以隐藏你的progressBarDialog
。
你也可以包含这个代码:
public class information extends AsyncTask<String, String, String> { @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(String... arg0) { return null; } @Override protected void onPostExecute(String result) { super.onPostExecute(result); this.cancel(true); } @Override protected void onProgressUpdate(String... values) { super.onProgressUpdate(values); } @Override protected void onCancelled() { Toast.makeText(getApplicationContext(), "asynctack cancelled.....", Toast.LENGTH_SHORT).show(); dialog.hide(); /*hide the progressbar dialog here...*/ super.onCancelled(); } }
你可以要求取消,但不能真正终止。 看到这个答案 。
大部分时间,我使用AsyncTask我的业务逻辑是在一个单独的业务类,而不是在用户界面上。 在这种情况下,我不能在doInBackground()中有一个循环。 一个例子就是一个消耗服务和一个接一个地持久化数据的同步过程。
我最终把我的任务交给业务对象,以便它能处理取消。 我的设置是这样的:
public abstract class MyActivity extends Activity { private Task mTask; private Business mBusiness; public void startTask() { if (mTask != null) { mTask.cancel(true); } mTask = new mTask(); mTask.execute(); } } protected class Task extends AsyncTask<Void, Void, Boolean> { @Override protected void onCancelled() { super.onCancelled(); mTask.cancel(true); // ask if user wants to try again } @Override protected Boolean doInBackground(Void... params) { return mBusiness.synchronize(this); } @Override protected void onPostExecute(Boolean result) { super.onPostExecute(result); mTask = null; if (result) { // done! } else { // ask if user wants to try again } } } public class Business { public boolean synchronize(AsyncTask<?, ?, ?> task) { boolean response = false; response = loadStuff(task); if (response) response = loadMoreStuff(task); return response; } private boolean loadStuff(AsyncTask<?, ?, ?> task) { if (task != null && task.isCancelled()) return false; // load stuff return true; } }
我有一个类似的问题 – 基本上是在用户摧毁了这个活动之后,我得到了一个asynchronous任务。 在研究堆栈溢出问题后,我采用了以下解决scheme:
volatile boolean running; public void onActivityCreated (Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); running=true; ... } public void onDestroy() { super.onDestroy(); running=false; ... }
然后,我在asynchronous代码中定期检查“如果正在运行”。 我有压力testing了这一点,我现在无法“打破”我的活动。 这完美的工作,并有比我看到的一些解决scheme更简单的优势。