Android - 为AsyncTask设置超时?

时间:2011-10-24 22:32:44

标签: java android android-asynctask

我执行了一个AsyncTask类,可以从网站下载大量数据。

如果最终用户在使用时数据连接速度非常慢或不稳定,我希望在一段时间后使AsyncTask超时。我的第一个方法是这样的:

MyDownloader downloader = new MyDownloader();
downloader.execute();
Handler handler = new Handler();
handler.postDelayed(new Runnable()
{
  @Override
  public void run() {
      if ( downloader.getStatus() == AsyncTask.Status.RUNNING )
          downloader.cancel(true);
  }
}, 30000 );

启动AsyncTask后,会启动一个新的处理程序,如果它仍在运行,它将在30秒后取消AsyncTask

这是一个好方法吗?或者AsyncTask内置的内容是否更适合此目的?

7 个答案:

答案 0 :(得分:41)

是的,有AsyncTask.get()

myDownloader.get(30000, TimeUnit.MILLISECONDS);

请注意,通过在主线程(AKA.UI线程)中调用它将阻止执行,您可能需要在单独的线程中调用它。

答案 1 :(得分:17)

在onPreExecute()方法的AsyncTask扩展类中使用CountDownTimer类:

主要优点是,在类内部完成异步监视。

public class YouExtendedClass extends AsyncTask<String,Integer,String> {
...
public YouExtendedClass asyncObject;   // as CountDownTimer has similar method -> to prevent shadowing
...
@Override
protected void onPreExecute() {
    asyncObject = this;
    new CountDownTimer(7000, 7000) {
        public void onTick(long millisUntilFinished) {
            // You can monitor the progress here as well by changing the onTick() time
        }
        public void onFinish() {
            // stop async task if not in progress
            if (asyncObject.getStatus() == AsyncTask.Status.RUNNING) {
                asyncObject.cancel(false);
                // Add any specific task you wish to do as your extended class variable works here as well.
            }
        }
    }.start();
...

更改CountDownTimer(7000,7000) - &gt;例如CountDownTimer(7000,1000),它会在调用onFinish()之前调用onTick()6次。如果您想添加一些监控,这很好。

感谢您在此页面中提供的所有好建议: - )

答案 2 :(得分:16)

在这种情况下,您的下载程序基于URL连接,您有许多参数可以帮助您定义超时而无需复杂的代码:

  HttpURLConnection urlc = (HttpURLConnection) url.openConnection();

  urlc.setConnectTimeout(15000);

  urlc.setReadTimeout(15000);

如果您只是将此代码带入异步任务,那就没关系。

&#39;阅读超时&#39;是在整个传输过程中测试一个糟糕的网络。

&#39;连接超时&#39;仅在开始时调用以测试服务器是否启动。

答案 3 :(得分:2)

我认为AsyncTask中没有内置的东西。你的方法似乎很好。只要确保在AsyncTask的doInBackground方法中定期检查isCancelled()的值,一旦UI线程取消它就结束此方法。

如果由于某种原因想要避免使用处理程序,可以在AsyncTask中定期检查System.currentTimeMillis并在超时时退出,尽管我更喜欢你的解决方案,因为它实际上可以中断线程。

答案 4 :(得分:0)

         Context mContext;

         @Override
         protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
                                    mContext = this;

            //async task
            final RunTask tsk = new RunTask (); 
            tsk.execute();

            //setting timeout thread for async task
            Thread thread1 = new Thread(){
            public void run(){
                try {
                    tsk.get(30000, TimeUnit.MILLISECONDS);  //set time in milisecond(in this timeout is 30 seconds

                } catch (Exception e) {
                    tsk.cancel(true);                           
                    ((Activity) mContext).runOnUiThread(new Runnable()
                    {
                         @SuppressLint("ShowToast")
                        public void run()
                         {
                            Toast.makeText(mContext, "Time Out.", Toast.LENGTH_LONG).show();
                            finish(); //will close the current activity comment if you don't want to close current activity.                                
                         }
                    });
                }
            }
        };
        thread1.start();

         }

答案 5 :(得分:0)

您可以再添加一个条件,以使取消更加健壮。如,

 if (downloader.getStatus() == AsyncTask.Status.RUNNING || downloader.getStatus() == AsyncTask.Status.PENDING)
     downloader.cancel(true);

答案 6 :(得分:0)

从问题中鼓舞我写了一个方法,通过AsyncTask执行一些后台任务,如果处理的次数超过了LOADING_TIMEOUT,则会出现重试的警告对话框。

public void loadData()
    {
        final Load loadUserList=new Load();
        loadUserList.execute();
        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                if (loadUserList.getStatus() == AsyncTask.Status.RUNNING) {
                    loadUserList.cancel(true);
                    pDialog.cancel();
                    new AlertDialog.Builder(UserList.this)
                            .setTitle("Error..!")
                            .setMessage("Sorry you dont have proper net connectivity..!\nCheck your internet settings or retry.")
                            .setCancelable(false)
                            .setPositiveButton("Retry", new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialogInterface, int i) {
                                    loadData();
                                }
                            })
                            .setNegativeButton("Exit", new DialogInterface.OnClickListener() {
                                @Override


                      public void onClick(DialogInterface dialogInterface, int i) {
                                System.exit(0);
                            }
                        })
                        .show();
            }
        }
    }, LOADING_TIMEOUT);
    return;
}