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 новый обработчик, который отменяет AsyncTask через 30 секунд, если он все еще работает.

Это хороший подход? Или есть что-то встроенное в AsyncTask , которое лучше подходит для этой цели?

Solutions Collecting From Web of "Android – настройка тайм-аута для AsyncTask?"

Да, есть AsyncTask.get ()

 myDownloader.get(30000, TimeUnit.MILLISECONDS); 

Обратите внимание, что, вызвав это в основном потоке (поток AKA. UI), будет блокировать выполнение, вероятно, вам нужно вызвать его в отдельном потоке.

В этом случае ваш загрузчик основан на URL-соединении, у вас есть несколько параметров, которые могут помочь вам определить тайм-аут без сложного кода:

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

Если вы просто принесли этот код в свою задачу async, все в порядке.

«Тайм-аут чтения» – это проверка плохой сети по всей передаче.

«Тайм-аут соединения» вызывается только в начале, чтобы проверить, установлен ли сервер или нет.

Используйте класс CountDownTimer в расширенном классе для AsyncTask в методе onPreExecute ():

Главное преимущество, мониторинг Async, выполненный внутри класса.

 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), и он вызовет onTick () 6 раз, прежде чем вызывать onFinish (). Это хорошо, если вы хотите добавить некоторый мониторинг.

Спасибо за все хорошие советы, которые я получил на этой странице 🙂

Я не думаю, что есть что-то вроде встроенного в AsyncTask. Ваш подход кажется хорошим. Просто не забудьте периодически проверять значение isCancelled () в методе doInBackground в AsyncTask, чтобы закончить этот метод, когда поток пользовательского интерфейса отменяет его.

Если вы хотите избежать использования обработчика по какой-либо причине, вы можете периодически проверять System.currentTimeMillis в своей AsyncTask и выходить из таймаута, хотя мне нравится ваше решение лучше, так как оно может фактически прервать поток.

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