Моя программа выполняет некоторую сетевую активность в фоновом потоке. Перед началом работы появляется диалоговое окно прогресса. Диалог закрывается на обработчике. Это все работает нормально, за исключением случаев, когда ориентация экрана изменяется, когда диалоговое окно открыто (и фоновая нить идет). В этот момент приложение либо вылетает, либо блокируется, либо попадает в странную стадию, когда приложение вообще не работает, пока все потоки не будут уничтожены.
Как я могу изящно справиться с изменением ориентации экрана?
Пример кода ниже примерно соответствует тому, что делает моя настоящая программа:
public class MyAct extends Activity implements Runnable {
public ProgressDialog mProgress;
// UI has a button that when pressed calls send
public void send() {
mProgress = ProgressDialog.show(this, "Please wait",
"Please wait",
true, true);
Thread thread = new Thread(this);
thread.start();
}
public void run() {
Thread.sleep(10000);
Message msg = new Message();
mHandler.sendMessage(msg);
}
private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mProgress.dismiss();
}
};
}
стек:
E/WindowManager( 244): Activity MyAct has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@433b7150 that was originally added here
E/WindowManager( 244): android.view.WindowLeaked: Activity MyAct has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@433b7150 that was originally added here
E/WindowManager( 244): at android.view.ViewRoot.<init>(ViewRoot.java:178)
E/WindowManager( 244): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:147)
E/WindowManager( 244): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:90)
E/WindowManager( 244): at android.view.Window$LocalWindowManager.addView(Window.java:393)
E/WindowManager( 244): at android.app.Dialog.show(Dialog.java:212)
E/WindowManager( 244): at android.app.ProgressDialog.show(ProgressDialog.java:103)
E/WindowManager( 244): at android.app.ProgressDialog.show(ProgressDialog.java:91)
E/WindowManager( 244): at MyAct.send(MyAct.java:294)
E/WindowManager( 244): at MyAct$4.onClick(MyAct.java:174)
E/WindowManager( 244): at android.view.View.performClick(View.java:2129)
E/WindowManager( 244): at android.view.View.onTouchEvent(View.java:3543)
E/WindowManager( 244): at android.widget.TextView.onTouchEvent(TextView.java:4664)
E/WindowManager( 244): at android.view.View.dispatchTouchEvent(View.java:3198)
Я пытался закрыть диалог прогресса в onSaveInstanceState, но это только предотвращает немедленный сбой. Фоновый поток все еще продолжается, а пользовательский интерфейс находится в частично отрисованном состоянии. Необходимо убить все приложение, прежде чем оно снова начнет работать.
источник
Ответы:
Когда вы меняете ориентацию, Android создаст новый вид. Вы, вероятно, получаете сбои, потому что ваш фоновый поток пытается изменить состояние старого. (Это также может быть проблема, потому что ваш фоновый поток не в потоке пользовательского интерфейса)
Я бы предложил сделать этот mHandler энергозависимым и обновлять его при изменении ориентации.
источник
Изменить: инженеры Google не рекомендуют этот подход, как описано Дайан Хэкборн (aka hackbod ) в этом сообщении StackOverflow . Проверьте это сообщение в блоге для получения дополнительной информации.
Вы должны добавить это к объявлению активности в манифесте:
так выглядит
Дело в том, что система уничтожает активность при изменении конфигурации. Смотрите ConfigurationChanges .
Таким образом, включение этого в файл конфигурации позволяет избежать разрушения вашей системы. Вместо этого он вызывает
onConfigurationChanged(Configuration)
метод.источник
orientation
, есть много других причин для изменения конфигурации:keyboardHidden
(я уже отредактировал ответ в вики),uiMode
(например, вход в или из режима автомобиля; смена ночного режима) и т. Д. Теперь я задаюсь вопросом, действительно ли это хороший ответ.Я придумал надежное решение для этих проблем, которое соответствует «Android Way» вещей. У меня есть все мои длительные операции с использованием шаблона IntentService.
То есть моя деятельность передает намерения, IntentService выполняет работу, сохраняет данные в БД и затем передает нежелательные намерения. Важная часть важна, так что даже если действие было приостановлено в течение времени после того, как пользователь начал работу и пропускает трансляцию в реальном времени от IntentService, мы все равно можем ответить и получить данные из вызывающего действия.
ProgressDialog
С этим шаблоном можно очень хорошо работатьonSaveInstanceState()
.По сути, вам нужно сохранить флаг, что у вас есть запущенный диалог в сохраненном экземпляре пакета. Не сохраняйте объект диалога прогресса, поскольку это приведет к утечке всей активности. Чтобы иметь постоянный дескриптор диалога прогресса, я храню его как слабую ссылку в объекте приложения. В случае изменения ориентации или чего-либо еще, что приводит к приостановке действия (телефонный звонок, пользователь попадает домой и т. Д.), А затем возобновляется, я закрываю старый диалог и заново создаю новый диалог во вновь созданном действии.
Для неопределенных диалогов прогресса это легко. Для стиля индикатора выполнения вы должны поместить последний известный прогресс в пакет и любую информацию, которую вы используете локально в упражнении, чтобы отслеживать прогресс. При восстановлении прогресса вы будете использовать эту информацию, чтобы повторно вызывать индикатор выполнения в том же состоянии, что и раньше, а затем обновлять его в зависимости от текущего состояния.
Итак, подведем итог: размещение долгосрочных задач в IntentService в сочетании с разумным использованием
onSaveInstanceState()
позволяет эффективно отслеживать диалоги и затем восстанавливать их в событиях жизненного цикла Activity. Соответствующие биты кода активности приведены ниже. Вам также понадобится логика в BroadcastReceiver для надлежащей обработки намерений Sticky, но это выходит за рамки этого.источник
Я встретил ту же проблему. Моя деятельность должна анализировать некоторые данные из URL, и это медленно. Поэтому я создаю поток для этого, а затем показываю диалог прогресса. Я позволил ветке опубликовать сообщение обратно в ветку пользовательского интерфейса,
Handler
когда она будет закончена. ВHandler.handleMessage
, я получаю объект данных (готово сейчас) из потока и заполняю его в пользовательский интерфейс. Так что это очень похоже на ваш пример.После долгих проб и ошибок похоже, что я нашел решение. По крайней мере, теперь я могу поворачивать экран в любой момент, до или после завершения потока. Во всех тестах диалоговое окно правильно закрывается, и все поведение соответствует ожидаемому.
То, что я сделал, показано ниже. Цель состоит в том, чтобы заполнить мою модель данных (
mDataObject
) и затем заполнить ее для пользовательского интерфейса. Должен позволить поворот экрана в любой момент без сюрпризов.Это то, что работает для меня. Я не знаю, является ли это «правильным» методом, разработанным Android - они утверждают, что эта операция «уничтожить / воссоздать во время поворота экрана» на самом деле облегчает ситуацию, поэтому я не думаю, что она не должна быть слишком сложной.
Дайте мне знать, если вы видите проблему в моем коде. Как сказано выше, я не знаю, есть ли побочный эффект.
источник
onRetainNonConfigurationInstance()
иgetLastNonConfigurationInstance()
помогла мне решить мою проблему. Недурно!Первоначальная проблема заключалась в том, что код не выдерживал изменения ориентации экрана. По-видимому, это было «решено», когда программа сама обрабатывала изменение ориентации экрана, а не позволяла каркасу пользовательского интерфейса (через вызов onDestroy)).
Я бы сказал, что если основная проблема заключается в том, что программа не выживет в Destroy (), то принятое решение - это просто обходной путь, который оставляет программу с другими серьезными проблемами и уязвимостями. Помните, что платформа Android специально заявляет, что ваша деятельность может быть уничтожена практически в любое время из-за обстоятельств, не зависящих от вас. Следовательно, ваша деятельность должна быть в состоянии пережить onDestroy () и последующую onCreate () по любой причине, а не только с изменением ориентации экрана.
Если вы собираетесь самостоятельно обрабатывать изменения ориентации экрана, чтобы решить проблему OP, вам необходимо убедиться, что другие причины onDestroy () не приводят к той же ошибке. Вы можете сделать это? Если нет, я бы спросил, действительно ли «принятый» ответ очень хороший.
источник
Моим решением было расширить
ProgressDialog
класс, чтобы получить свой собственныйMyProgressDialog
.Я переопределил
show()
иdismiss()
методы, чтобы заблокировать ориентацию, прежде чем показыватьDialog
и разблокировать его обратно, когдаDialog
уволен. Таким образом, когдаDialog
отображается и ориентация устройства изменяется, ориентация экрана сохраняется до тех пор, пока неdismiss()
будет вызван, тогда ориентация экрана изменяется в соответствии со значениями датчика / ориентации устройства.Вот мой код:
источник
Я столкнулся с той же проблемой, и я нашел решение, которое не требует использования ProgressDialog, и я получаю более быстрые результаты.
Что я сделал, так это создал макет, в котором есть ProgressBar.
Затем в методе onCreate сделайте следующее
Затем выполните длинную задачу в потоке, и когда она будет завершена, запустите Runnable, чтобы установить представление контента в реальный макет, который вы хотите использовать для этого действия.
Например:
Это то, что я сделал, и я обнаружил, что он работает быстрее, чем отображение ProgressDialog, и он менее навязчив и выглядит лучше, на мой взгляд.
Однако, если вы хотите использовать ProgressDialog, тогда этот ответ не для вас.
источник
setContentView(R.layout.my_layout);
недостаточно; вам нужно установить всех слушателей, сбросить данные и т. д.Я нашел решение для этого, которого я еще не видел в другом месте. Вы можете использовать пользовательский объект приложения, который знает, выполняются ли фоновые задачи, вместо того, чтобы пытаться делать это в действии, которое уничтожается и воссоздается при изменении ориентации. Я писал об этом здесь .
источник
Application
обычно используется для поддержания глобального состояния приложения. Я не говорю, что это не работает, но это кажется слишком сложным. Из документа «Обычно нет необходимости создавать подкласс приложения». Я в основном предпочитаю ответ Sonxurxo.Я собираюсь внести свой подход к решению этой проблемы ротации. Это может не относиться к OP, так как он не использует
AsyncTask
, но, возможно, другие найдут его полезным. Это довольно просто, но, кажется, делает эту работу за меня:У меня есть вход в систему с вложенным
AsyncTask
классом под названиемBackgroundLoginTask
.По моему,
BackgroundLoginTask
я не делаю ничего необычного, кроме добавления нулевой проверки при вызовеProgressDialog
dismiss:Это
Activity
сделано для того, чтобы справиться со случаем, когда фоновая задача завершается, когда она не видна, и, следовательно, диалоговое окно прогресса уже закрытоonPause()
методом.Затем в своем родительском
Activity
классе я создаю глобальные статические дескрипторы для своегоAsyncTask
класса и мойProgressDialog
(AsyncTask
будучи вложенным, может обращаться к этим переменным):Это служит двум целям: во-первых, это позволяет мне
Activity
всегда получать доступ кAsyncTask
объекту даже после нового, пост-ротационного действия. Во-вторых, это позволяет мнеBackgroundLoginTask
получить доступ и отклонитьProgressDialog
даже после поворота.Затем я добавляю это к
onPause()
, вызывая исчезновение диалогового окна прогресса, когда мыActivity
покидаем передний план (предотвращая этот ужасный сбой принудительного закрытия):Наконец, у меня есть следующее в моем
onResume()
методе:Это позволяет
Dialog
вновь появиться послеActivity
воссоздания.Вот весь класс:
Я ни в коем случае не опытный разработчик Android, поэтому не стесняйтесь комментировать.
источник
Переместите длинное задание в отдельный класс. Реализуйте это как образец субъекта-наблюдателя. Всякий раз, когда создается действие, регистрируйтесь, а при закрытии отменяйте регистрацию с помощью класса задач. Класс задачи может использовать AsyncTask.
источник
Хитрость заключается в том, чтобы показать / закрыть диалоговое окно в AsyncTask во время onPreExecute / onPostExecute как обычно, хотя в случае изменения ориентации создайте / покажите новый экземпляр диалога в действии и передайте его ссылку на задачу.
источник
Я сделал это так:
Вы также можете попробовать сообщить мне, это работает для вас или нет
источник
Если вы создаете фон,
Service
который выполняет всю тяжелую работу (запросы / ответы tcp, unmarshalling),View
иActivity
могут быть уничтожены и воссозданы без утечки окна или потери данных. Это позволяет поведение, рекомендуемое Android, которое заключается в уничтожении активности при каждом изменении конфигурации. (например, при каждом изменении ориентации).Это немного сложнее, но это лучший способ для вызова запроса к серверу, предварительной / последующей обработки данных и т. Д.
Вы можете даже использовать свой
Service
команду для постановки каждого запроса на сервер, чтобы вам было легко и эффективно справляться с этими задачами.У руководства разработчика есть полная глава
Services
.источник
Service
это больше работа, чем,AsyncTask
но может быть лучшим подходом в некоторых ситуациях. Это не обязательно лучше, не так ли? При этом я не понимаю, как это решает проблемуProgressDialog
утечки из основногоActivity
. Где вы воплощаетеProgressDialog
? Где вы это отклоняете?У меня есть реализация, которая позволяет уничтожить действие при изменении ориентации экрана, но все еще успешно уничтожает диалог в воссозданном действии. я использую
...NonConfigurationInstance
чтобы прикрепить фоновое задание к воссозданному действию. Нормальный фреймворк Android обрабатывает воссоздание самого диалога, там ничего не меняется.Я вложил в подкласс AsyncTask добавление поля для действия «владелец» и метода для обновления этого владельца.
В своем классе деятельности я добавил поле,
backgroundTask
относящееся к «собственной» фоновой задаче, и я обновляю это поле, используяonRetainNonConfigurationInstance
иgetLastNonConfigurationInstance
.Предложения по дальнейшему улучшению:
backgroundTask
ссылку в действии после завершения задачи, чтобы освободить любую память или другие ресурсы, связанные с ней.ownerActivity
ссылку в фоновой задаче перед уничтожением действия, если оно не будет немедленно воссоздано.BackgroundTask
интерфейс и / или коллекцию, позволяющую запускать различные типы задач из одного и того же владельца.источник
Если вы поддерживаете два макета, весь поток пользовательского интерфейса должен быть прерван.
Если вы используете AsynTask, то вы можете легко вызвать
.cancel()
метод внутриonDestroy()
метода текущей активности.Для AsyncTask читайте больше в разделе «Отмена задачи» здесь .
Обновление: добавлено условие для проверки статуса, так как его можно отменить, только если он находится в рабочем состоянии. Также обратите внимание, что AsyncTask может быть выполнен только один раз.
источник
Попытался внедрить решение jfelectron , потому что это « надежное решение этих проблем, которое соответствует« Android Way »вещей », но потребовалось некоторое время, чтобы найти и собрать все упомянутые элементы. Закончилось этим немного по-другому, и я думаю, что более элегантное решение выложено здесь полностью.
Использует IntentService, запущенный из действия, для выполнения длительной задачи в отдельном потоке. Служба запускает липкие Broadcast Intents для действия, которое обновляет диалог. Упражнение использует showDialog (), onCreateDialog () и onPrepareDialog (), чтобы исключить необходимость передачи постоянных данных в объект приложения или в комплекте saveInstanceState. Это должно работать независимо от того, как ваше приложение прерывается.
Класс деятельности:
Класс IntentService:
Записи файла манифеста:
перед разделом приложения:
внутри раздела приложения
источник
Это мое предлагаемое решение:
void showProgressDialog()
этой цели в интерфейс прослушивателя фрагмента-активности можно добавить метод.источник
Я столкнулся с такой же ситуацией. Я получил только один экземпляр для моего диалога прогресса во всем приложении.
Сначала я создал класс DialogSingleton, чтобы получить только один экземпляр (шаблон Singleton)
Как я показываю в этом классе, у меня есть диалог прогресса как атрибут. Каждый раз, когда мне нужно показать диалог прогресса, я получаю уникальный экземпляр и создаю новый ProgressDialog.
Когда я закончу с фоновой задачей, я снова вызываю уникальный экземпляр и закрываю его диалог.
Я сохраняю статус фоновой задачи в моих общих настройках. Когда я поворачиваю экран, я спрашиваю, запущено ли у меня задание для этого действия: (onCreate)
Когда я запускаю фоновую задачу:
Когда я закончу запуск фоновой задачи:
Я надеюсь, что это помогает.
источник
Это очень старый вопрос, который почему-то возник на боковой панели.
Если фоновой задаче необходимо выжить, пока активность находится на переднем плане, «новым» решением является размещение фонового потока (или, предпочтительно,
AsyncTask
) в сохраненном фрагменте , как описано в этом руководстве разработчика и многочисленных вопросах и ответах .Сохраненный фрагмент выживает, если действие уничтожается для изменения конфигурации, но не тогда, когда действие уничтожается в фоновом или заднем стеке. Следовательно, фоновое задание все равно должно быть прервано, если значение
isChangingConfigurations()
равно falseonPause()
.источник
Я более свежий в Android, и я попробовал это, и это сработало.
источник
Я пробовал ВСЕ. Провел дни экспериментов. Я не хотел блокировать вращение активности. Мой сценарий был:
Проблема заключалась в том, что при повороте экрана каждое решение в книге не удавалось. Даже с классом AsyncTask, который является правильным способом Android в таких ситуациях. При повороте экрана текущий контекст, с которым работает начальный поток, исчезает, и это портится в отображаемом диалоговом окне. Проблема всегда заключалась в диалоге, независимо от того, сколько трюков я добавил в код (передача нового контекста запущенным потокам, сохранение состояний потоков посредством вращений и т. Д.). Сложность кода в конце всегда была огромной, и всегда было что-то, что могло пойти не так.
Единственное решение, которое сработало для меня, это трюк «Активность / Диалог». Это просто и гениально, и все это доказательство вращения:
Вместо того, чтобы создавать диалог и просить показать его, создайте действие, которое было установлено в манифесте с android: theme = "@ android: style / Theme.Dialog". Итак, это просто выглядит как диалог.
Замените showDialog (DIALOG_ID) на startActivityForResult (yourActivityDialog, yourCode);
Используйте onActivityResult в вызывающем Activity, чтобы получить результаты из выполняющегося потока (даже ошибки) и обновить пользовательский интерфейс.
На вашем ActivityDialog используйте потоки или AsyncTask для выполнения длинных задач и onRetainNonConfigurationInstance для сохранения состояния «диалога» при повороте экрана.
Это быстро и отлично работает. Я все еще использую диалоги для других задач и AsyncTask для чего-то, что не требует постоянного диалога на экране. Но в этом сценарии я всегда использую шаблон «Активность / Диалог».
И я не пробовал, но даже можно заблокировать вращение Activity / Dialog во время работы потока, ускорить процесс и позволить вращающейся вызывающей Activity.
источник
Intent
, что является более ограничительным, чемObject
разрешеноAsyncTask
В наши дни есть гораздо более четкий способ решения подобных проблем. Типичный подход:
1. Убедитесь, что ваши данные правильно отделены от пользовательского интерфейса:
Все, что является фоновым процессом, должно быть сохранено
Fragment
(установите это с помощьюFragment.setRetainInstance()
. Это станет вашим «постоянным хранилищем данных», где хранятся все данные на основе, которые вы хотели бы сохранить. После события изменения ориентации этоFragment
все равно будет доступно в исходном виде состояние черезFragmentManager.findFragmentByTag()
вызов (когда вы создаете его, вы должны дать ему тег, а не идентификатор, поскольку он не привязан к aView
).См. Разработанное руководство по обработке изменений времени выполнения для получения информации о том, как сделать это правильно и почему это лучший вариант.
2. Убедитесь, что вы правильно и безопасно взаимодействуете между фоновыми процессами и вашим пользовательским интерфейсом:
Вы должны полностью изменить процесс связывания. В настоящий момент ваш фоновый процесс присоединяется к a
View
- вместо этого выView
должны присоединиться к фоновому процессу. Это имеет больше смысла, верно? ВView
действии «S зависит от фонового процесса, в то время как фоновый процесс не зависит отView
средств .Эты изменяющихся ссылку на стандартныйListener
интерфейс. Произнесите процесс (независимо от класса это - является ли оноAsyncTask
,Runnable
или любым другим ) определяетOnProcessFinishedListener
, когда процесс сделан он должен вызвать этот слушатель , если он существует.Этот ответ - хорошее краткое описание того, как сделать пользовательских слушателей.
3. Свяжите свой пользовательский интерфейс с процессом обработки данных при каждом создании пользовательского интерфейса (включая изменения ориентации):
Теперь вы должны беспокоиться о сопряжении фоновой задачи с текущей
View
структурой. Если вы обрабатываете изменения ориентации должным образом (неconfigChanges
всегда рекомендуют хакеры), то ваша системаDialog
будет воссоздана заново. Это важно, это означает, что при изменении ориентации все вашиDialog
жизненные циклы вспоминаются. Таким образом, в любом из этих методов (onCreateDialog
обычно это хорошее место) вы можете сделать вызов, подобный следующему:См. Жизненный цикл фрагмента, чтобы решить, где настройка слушателя лучше всего подходит для вашей индивидуальной реализации.
Это общий подход к обеспечению надежного и полного решения общей проблемы, задаваемой в этом вопросе. Вероятно, в этом ответе пропущено несколько незначительных частей в зависимости от вашего индивидуального сценария, но, как правило, это наиболее правильный подход для правильной обработки событий изменения ориентации.
источник
Я нашел и более простое решение для обработки потоков при изменении ориентации. Вы можете просто сохранить статическую ссылку на вашу деятельность / фрагмент и проверить, имеет ли оно значение null, прежде чем действовать на пользовательский интерфейс. Я предлагаю также использовать попытку catch:
источник
Если вы боретесь с обнаружением событий изменения ориентации в диалоге НЕЗАВИСИМЫЙ ОТ ССЫЛКИ О ДЕЯТЕЛЬНОСТИ , этот метод работает потрясающе хорошо. Я использую это, потому что у меня есть свой собственный класс диалога, который может отображаться в нескольких различных действиях, поэтому я не всегда знаю, в каком действии он отображается. С этим методом вам не нужно изменять AndroidManifest, беспокойтесь о ссылках на действия, и вам не нужен пользовательский диалог (как у меня). Тем не менее, вам нужен пользовательский вид контента, чтобы вы могли обнаружить изменения ориентации, используя этот конкретный вид. Вот мой пример:
Настроить
Реализация 1 - Диалог
Реализация 2 - AlertDialog.Builder
Реализация 3 - ProgressDialog / AlertDialog
источник
Это мое решение, когда я столкнулся с этим:
ProgressDialog
это неFragment
ребенок, поэтому мой пользовательский класс "ProgressDialogFragment
" может расширятьсяDialogFragment
вместо этого, чтобы сохранить диалоговое окно, отображаемое для изменений конфигурации.Есть 2 подхода для решения этой проблемы:
Первый подход: выполните действие, которое использует диалог для сохранения состояния во время изменения конфигурации в файле манифеста:
Этот подход не является предпочтительным для Google.
Второй подход: в
onCreate()
методе действия вам нужно сохранитьDialogFragment
его, перестроивProgressDialogFragment
заново с заголовком и сообщением, как показано ниже, если значениеsavedInstanceState
не равно NULL:источник
Кажется слишком «быстрым и грязным», чтобы быть правдой, поэтому, пожалуйста, укажите на недостатки, но я обнаружил, что сработало ...
В методе onPostExecute моего AsyncTask я просто обернул '.dismiss' для диалогового окна прогресса в блоке try / catch (с пустым catch), а затем просто проигнорировал возникшее исключение. Кажется, что это неправильно, но похоже, что нет никаких вредных последствий (по крайней мере, для того, что я делаю впоследствии, чтобы начать другую операцию, передаваемую в результате моего длительного выполнения запроса как Дополнительный)
источник
Activity
ссылка имеет отношение кDialog
. Когда конфигурация изменяется, первоеActivity
уничтожается, что означает, что все поля установлены вnull
. Но низкий уровеньWindowManager
также имеет ссылку наDialog
(поскольку он еще не был отклонен). НовыйActivity
пытается создать новыйDialog
(inpreExecute()
), и оконный менеджер вызывает фатальное исключение, мешающее вам сделать это. Действительно, если это произойдет, не будет никакого способа полностью уничтожить,Dialog
следовательно, сохраняя ссылку на начальноеActivity
. Я прав?Самое простое и гибкое решение - использовать AsyncTask со статической ссылкой на ProgressBar . Это обеспечивает инкапсулированное и, следовательно, многоразовое решение проблем изменения ориентации. Это решение хорошо мне помогло при решении различных асинхронных задач, включая загрузку через Интернет, обмен данными со службами и сканирование файловой системы. Решение было хорошо протестировано на нескольких версиях Android и моделях телефонов. Полная демонстрация может быть найдена здесь с особым интересом в DownloadFile.java
Я представляю следующее в качестве примера концепции
Использование в Android-деятельности просто
источник
Когда вы меняете ориентацию, Android убивает это действие и создает новое действие. Я предлагаю использовать модификацию с Rx Java. который обрабатывает сбой автоматически.
Используйте этот метод при модификации вызова.
.subscribeOn (Schedulers.io ()) .observeOn (AndroidSchedulers.mainThread ())
источник