Intereting Posts
Как подключиться к нескольким базам данных с помощью JPA? Каковы ваши мысли о константах, связанных с методом? Как апплет чтения / записи файлов в локальной файловой системе? Проблемы с генерацией кода авторизации и токена пользователя с использованием библиотеки Apache OAuth client 2.0 в Java java Сопоставление панели BoxLayout Использование DateTimeFormatter в январе сначала приводит к недопустимому значению года Как я могу надежно имитировать сенсорные события на Android без root (например, Automate и Tasker)? Как я могу создать кучу кучи только с JRE? Java: замена текстового URL с помощью интерактивной HTML-ссылки Почему в нем говорится, что «Нельзя ссылаться на не конечную переменную i внутри внутреннего classа, определенного другим методом»? внутренний доступ classа к методу внешнего classа, те же имена методов Нужен образец проекта Android REST Client, который реализует образец реализации Вершина Добжански REST Как найти с помощью Java, если определенный шрифт установлен правильно на машине Автоматическое выполнение плагина eclipse Заполнение hash-карты с предопределенными значениями (java)

Метод get () AsyncTask: есть ли какой-либо сценарий, где это действительно лучший вариант?

Отвечая на этот вопрос, я получил сомнение в смысле / полезности использования метода get () для classа AsyncTask для Android.

public final Result get () Waits if necessary for the computation to complete, and then retrieves its result. 

В принципе, это синхронное решение для classа AsyncTask, которое блокирует (замораживает) пользовательский интерфейс до завершения фоновых операций.

Помимо пробных целей, и даже в тех случаях, я не могу думать ни о каком сценарии, где это на самом деле хорошее решение, но я могу ошибаться, поэтому мне становится любопытно.

Если вам нужно, чтобы пользователь дождался окончания работы AsyncTask, вы можете показать Dialog или ProgressDialog, каждый раз контролируя интерфейс. Я знаю, что это не совсем то же самое, но IMHO это гораздо лучший подход, чем использование метода get() .

AsyncTask – не единственный способ делать фоновые операции. В самом деле, в документации говорится, что AsyncTask следует использовать только для операций, AsyncTask не более нескольких секунд. Поэтому, если у вас есть задачи, которые занимают больше времени, они должны быть закодированы через classы, реализующие интерфейс runnable . Такие задачи в других (не AsyncTask) streamах вполне могут подождать AsyncTask , поэтому мне кажется, что идея о том, что нет ситуаций, когда вы хотите использовать AsyncTask.get() является ложью.

Обновление. В ответ на комментарий, чтобы подчеркнуть, что это может быть допустимым использованием AsyncTask.get() , возможно следующее:

  • AsyncTask существовать AsyncTask s, который инициируется из streamа пользовательского интерфейса, который может включать обмен через Интернет, например, загрузку веб-страницы или связь с сервером. Независимо от результатов AsyncTask , некоторые (или все) результаты необходимы для обновления экрана. Следовательно, AsyncTask с его doInBackground за которым следует onPostExecute в streamе пользовательского интерфейса, имеет смысл.
  • Всякий раз, когда stream пользовательского интерфейса инициирует AsyncTask , он помещает объект AsyncTask в очередь, для дополнительной обработки отдельным фоновым streamом после получения результатов.
  • Для каждой очереди AsyncTask в очереди в фоновом streamе используется AsyncTask.get() чтобы дождаться завершения задачи, прежде чем выполнять дополнительную обработку. Одним очевидным примером дополнительной обработки может быть просто регистрация всех таких действий AsyncTask на сервере в Интернете, поэтому имеет смысл сделать это в фоновом режиме.

Следующий код показывает, что я имею в виду. Приложение вызывает KickOffAsynctask(...) когда захочет сделать AsyncTask, и есть фоновый stream, который автоматически выполнит задачу для последующей обработки после завершения задачи.

 public class MyActivity extends Activity { static class MyAsyncTaskParameters { } static class MyAsyncTaskResults { } Queue queue; // task queue for post-processing of AsyncTasks in the background BackgroundThread b_thread; // class related to the background thread that does the post-processing of AsyncTasks @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); queue = new ConcurrentLinkedQueue(); b_thread = new BackgroundThread(queue); b_thread.Start(); } void KickOffAsynctask(MyAsyncTaskParameters params) { MyAsyncTask newtask = new MyAsyncTask(); newtask.execute(params); synchronized(queue) { queue.add(newtask); } } static class MyAsyncTask extends AsyncTask { @Override protected MyAsyncTaskResults doInBackground(MyAsyncTaskParameters... params) { MyAsyncTaskResults results = new MyAsyncTaskResults(); // do AsyncTask in background return results; } @Override protected void onPostExecute(MyAsyncTaskResults res){ // take required results from MyAsyncResults for use in the user interface } } static class BackgroundThread implements Runnable { // class that controls the post processing of AsyncTask results in background private Queue queue; private Thread thisthread; public boolean continue_running; public BackgroundThread(Queue queue) { this.queue=queue; thisthread = null; continue_running = true; } public void Start() { thisthread = new Thread(this); thisthread.start(); } @Override public void run() { try { do { MyAsyncTask task; synchronized(queue) { task = queue.poll(); } if (task == null) { Thread.sleep(100); } else { MyAsyncTaskResults results = task.get(); // post processing of AsyncTask results in background, eg log to a server somewhere } } while (continue_running); } catch(Throwable e) { e.printStackTrace(); } } } } 

Обновление2 . Другое возможное использование AsyncTask.get() произошло со мной. Стандартный совет – не использовать AsyncTask.get() из streamа пользовательского интерфейса, поскольку он заставляет пользовательский интерфейс зависеть до тех пор, пока результат не будет доступен. Однако для приложения, где требуется скрытность, это может быть именно то, что требуется. Итак, как насчет следующей ситуации: Джеймс Бонд прорывается в гостиничный номер Le Chiffre и имеет только пару минут, чтобы извлечь все данные с телефона ворсина и установить контрольный вирус. Он устанавливает приложение, предоставляемое Q, и запускает его, но он слышит, как кто-то идет, чтобы он скрывался. Ле Чифре входит в комнату и берет трубку, чтобы позвонить. На несколько секунд телефон кажется немного невосприимчивым, но вдруг телефон просыпается, и он делает свой телефонный звонок без дальнейших размышлений. Разумеется, причиной невнимательности был тот факт, что приложение Q работает. Ему приходилось выполнять различные задачи, и некоторые из них должны выполняться в определенном порядке. Приложение использовало два streamа для выполнения работы, а именно сам пользовательский интерфейс и единственный фоновый stream, который обрабатывает AsyncTask s. Пользовательский интерфейс полностью контролировал все задачи, но из-за того, что некоторые задачи нужно было выполнять перед другими задачами, в приложении присутствовали точки, в которых stream пользовательского интерфейса использовал AsyncTask.get() , ожидая завершения фоновой задачи: ).

Метод get никогда не должен использоваться в streamе пользовательского интерфейса, потому что он (как вы заметили) заморозит ваш пользовательский интерфейс. Он должен использоваться в фоновом streamе, чтобы дождаться конца вашей задачи, но, как правило, старайтесь избегать AsyncTask как можно больше ( ПОЧЕМУ? ).

Я бы предложил callback или eventbus в качестве замены.

если вы запускаете несколько асинхронных задач параллельно, вам может потребоваться, чтобы некоторые задачи ожидали результата других.

однако, я думаю, вам следует избегать запуска слишком много асинхронных задач параллельно, потому что это замедлит работу устройства.

Обычно я использую class обработчика, чтобы выполнить трюк (загрузка асинхронного носителя). Подобно:

 public void setRightSongAdele(Song current) { RetriveCorrelateGenreSong rcgs = new RetriveCorrelateGenreSong(current); new Thread(rcgs).start(); } @SuppressLint("HandlerLeak") Handler updateRightAdeleHandler = new Handler() { @Override public void handleMessage(Message msg) { songNextText.setText(utils.reduceStringLength(rightSong.getTitle(), 15)); adeleNext.setImageBitmap(utils.getAlbumArtFromSong(rightSong.getPath(), getApplicationContext())); } }; 

Я отправляю свой собственный ответ, поскольку это то, что я думаю в этот момент, и никто не дал его.

Мое любопытство все еще живое, поэтому я не буду отмечать это правильно. Если кто-то ответит на этот вопрос блестяще, я буду отмечать его / ее ответ как правильный.

Мой ответ заключается в том, что на самом деле нет сценария, где использование метода get() AsyncTask является лучшим решением.

ИМХО, используя этот метод, бессмыслен. Я имею в виду, что всегда кажется лучшим решением.

Аналогично, я бы сказал, что это семантически шокирует, так как его обращение изменяет вашу AsyncTask в эффективную «SyncTask».

Поскольку документация стоит:

«Ожидает, если это необходимо для завершения вычисления, а затем извлекает его результат».

Поэтому обязательно, чтобы вы не вызывали его в NetworkOnMainThreadException пользовательского интерфейса, иначе вы получите NetworkOnMainThreadException . Я бы использовал его в тестовой среде, которая включает в себя сетевые операции или подождать еще одну задачу.

EDIT: я ошибся в NetworkOnMainThreadException .

Кажется, AsyncTask.get () блокирует stream вызывающего, где AsyncTask.execute () не работает.

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

Синтаксис такой же, как и выполнить:

  private class DownloadFilesTask extends AsyncTask { protected Long doInBackground(URL... urls) { int count = urls.length; long totalSize = 0; for (int i = 0; i < count; i++) { totalSize += Downloader.downloadFile(urls[i]); publishProgress((int) ((i / (float) count) * 100)); } return totalSize; } protected void onProgressUpdate(Integer... progress) { setProgressPercent(progress[0]); } protected void onPostExecute(Long result) { showDialog("Downloaded " + result + " bytes"); } } new DownloadFilesTask().get(5000, TimeUnit.MILLISECONDS); 

Вы можете использовать его в своем адаптере адаптера AutoCompleteTextView.

 private class Adapter extends BaseAdapter implements Filterable{ getFilter(){ return new Filter() { @Override protected FilterResults performFiltering(CharSequence constraint) { List suggestions = MyApiSuggestionsApi(constraint).get(); return packageAsFilterResults(suggestions); } } } 

У меня есть приложение для редактирования фотографий, пользователь может открывать фотографии из URL-адресов.

Я использовал AsyncTask для загрузки фотографии с URL-адреса, в течение этого времени пользовательский интерфейс должен быть заблокирован. что я сделал, я показал, что ProgressBar запускает метод get () AsyncTask, чем скрывает ProgressBar.

Это казалось лучшим и самым простым решением для меня.