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更适合这个目的?

是的,有AsyncTask.get()

 myDownloader.get(30000, TimeUnit.MILLISECONDS); 

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

在这种情况下,您的下载程序基于URL连接,您可以使用一些参数来帮助您定义没有复杂代码的超时:

  HttpURLConnection urlc = (HttpURLConnection) url.openConnection(); urlc.setConnectTimeout(15000); urlc.setReadTimeout(15000); 

如果你只是把这个代码放到你的asynchronous任务中,那就没关系。

“读取超时”是在转移过程中testing不良networking。

“连接超时”仅在开始时调用以testing服务器是否启动。

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

主要优点,在课堂上内部完成的asynchronous监控。

 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) – > CountDownTimer(7000,1000)为例,它会在调用onFinish()之前调用onTick()6次。 如果你想添加一些监控,这是很好的。

感谢所有在这个页面上的好build议:-)

我不认为有像AsyncTask内置的东西。 你的方法似乎是一个很好的方法。 只要确保定期检查AsyncTask的doInBackground方法中isCancelled()的值,以在UI线程取消该方法时结束此方法。

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

  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(); } 

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

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

鼓舞人心的问题我已经写了一个方法,通过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; }