zoukankan      html  css  js  c++  java
  • Android AsyncTask 的实现及 cancel 方式

    最近做一个功能需要用到AsyncTask。实现的过程很容易,但是在cancel的时候遇到了一点麻烦。找了很多地方终于找到了比较好的方法,这里跟大家分享一下。


    根据Android Developer的介绍http://developer.android.com/intl/zh-CN/reference/android/os/AsyncTask.html :

    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。这里贴一段我写的代码,有点点改动。

    AsyncTask
     1     private class OpenWebPortalTask extends AsyncTask<Void, Void, Void> {
     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                 @Override
    14                 public void onCancel(DialogInterface dialog) {
    15                     cancel(true);
    16                 }
    17             });
    18         }
    19         
    20         @Override
    21         protected void onPreExecute(){
    22             mProgressDialog.show();
    23         }
    24         
    25         @Override
    26         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         @Override
    49         protected void onPostExecute(Void v) {
    50             mActivity.runOnUiThread(new Runnable() {
    51                 @Override
    52                 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的方法:

    1. 在ProgressDialog的setOnCancelListener里调用cancel(true);,表示如果ProgressDialog被cancel的话,也cancel掉AsyncTask;
    2. 在doInBackgroud方法中,判断isCancelled()是否为真,如果真,那么就返回。

    为什么在doInBackgroud中判断?因为AsyncTask的重要工作都是在doInBackgroud中完成,它如果退出了,那么就意味着AsyncTask将被销毁了。

    具体在doInBackgroud的哪部分判断是否要退出呢?这就需要根据程序的逻辑。一般在耗时操作的后面加上判断!代码中可以根据需要加多个这样的判断。


    AsyncTask用于实现一些简单的多线程任务确实非常简单和好用,希望对大家有所帮助。

  • 相关阅读:
    [Delphi]ListView基本用法大全
    Delphi 数据类型列表
    什么是堆、栈?
    使用钩子函数[1]
    邻道干扰
    内存管理[1]
    c#中复制类提示“Resource”参数不支持重复项的解决办法
    转帖:IE对话框showModalDialog(模态)和showModelessDialog
    今日工作心得:一段用于验证的jQuery代码
    每个开发人员现在应该下载的十种必备工具
  • 原文地址:https://www.cnblogs.com/wangfenjin/p/2696905.html
Copyright © 2011-2022 走看看