最近做一个功能需要用到AsyncTask。实现的过程很容易,但是在cancel的时候遇到了一点麻烦。找了很多地方终于找到了比较好的方法,这里跟大家分享一下。
根据Android Developer的介绍 :
AsyncTask enables proper and easy use of the UI thread. This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.
AsyncTask其实是Android给开发者提供的一个简单轻量级的多线程类,通过它我们可以很容易新建一个线程做一些耗时的操作,并在这个过程中更新UI。之所以说它轻量级,是因为缺少了直接使用Thread的灵活性。如果是很复杂的操作,还是建议通过Thread来操作,然后通过Broadcast的方式来更新UI。
使用AsyncTask的时候还需要注意,如果AsyncTask在运行过程中使用了某个activity,那么我们就需要在保证AsyncTask的运行过程中这个activity不被destory,或者是在activity的onDestory()方法里面cancel掉这个AsyncTask。但是,如果是一直不让activity被destory的话,相当于不让用户切换界面,这个体验其实时不好的。所以,我们最好使用ProgressDialog,让用户知道我们在努力完成他们的操作,为了让用户可以cancel这个操作,我们可以检测ProgressDialog有没有取消,如果取消了,那就cancel整个AsyncTask。
所以,我们总是会需要cancel AsyncTask。这里贴一段我写的代码,有点点改动。
1 private class OpenWebPortalTask extends AsyncTask{ 2 private static final String DEFAULT_URL = "https://www.google.com"; 3 private ProgressDialog mProgressDialog = null; 4 private Activity mActivity; 5 6 public OpenWebPortalTask(Activity activity){ 7 mActivity = activity; 8 mProgressDialog = new ProgressDialog(mActivity); 9 mProgressDialog.setMessage(getString(R.string.open_aweb_portal));10 mProgressDialog.setCancelable(true);11 mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {12 13 @Override14 public void onCancel(DialogInterface dialog) {15 cancel(true);16 }17 });18 }19 20 @Override21 protected void onPreExecute(){22 mProgressDialog.show();23 }24 25 @Override26 protected Void doInBackground(Void... params) {27 String schemeUrl = PropertyMgr.getInstance().getPortalURI();28 if (TextUtils.isEmpty(schemeUrl)) {29 schemeUrl = DEFAULT_ANTI_THEFT_URL;30 }31 try {32 String st = CredentialManager.getInstance().getServiceTicket();33 if(st != null) {34 schemeUrl += "?st=" + st;35 }36 } catch (Exception e) {37 SymLog.e(TAG, "Get Service Ticket failed.");38 }39 if(isCancelled()) {40 return null;41 }42 Intent i = new Intent(Intent.ACTION_VIEW);43 i.setData(Uri.parse(schemeUrl));44 startActivity(i);45 return null;46 }47 48 @Override49 protected void onPostExecute(Void v) {50 mActivity.runOnUiThread(new Runnable() {51 @Override52 public void run() {53 if (mProgressDialog != null) {54 mProgressDialog.dismiss();55 mProgressDialog = null;56 }57 }58 });59 }60 }
这段代码里面,
String st = CredentialManager.getInstance().getServiceTicket();
是个耗时操作,所以需要放在AsyncTask里面。例子中,在onPreExecute中显示ProgressDialog,在onPostExecute中销毁。
注意cancel AsyncTask的方法:
- 在ProgressDialog的setOnCancelListener里调用cancel(true);,表示如果ProgressDialog被cancel的话,也cancel掉AsyncTask;
- 在doInBackgroud方法中,判断isCancelled()是否为真,如果真,那么就返回。
为什么在doInBackgroud中判断?因为AsyncTask的重要工作都是在doInBackgroud中完成,它如果退出了,那么就意味着AsyncTask将被销毁了。
具体在doInBackgroud的哪部分判断是否要退出呢?这就需要根据程序的逻辑。一般在耗时操作的后面加上判断!代码中可以根据需要加多个这样的判断。
AsyncTask用于实现一些简单的多线程任务确实非常简单和好用,希望对大家有所帮助。