Лучшая практика для изменения ориентации: Android
Я занимался различными практиками для обработки изменений ориентации с помощью потоков и AsyncTask. Я наткнулся на следующие решения:
-
Модель прикрепления-отсоединения: Присоединение и отключение активности к потокам и AsyncTask при сохранении их экземпляра. (Источник: 1, 2)
-
Безголовый фрагмент: Использование фрагмента без UI/headless для выполнения всех операций, связанных с потоком, и сохранения его экземпляра при изменении конфигурации. (Источник: 1, 2)
Существуют ли какие-либо другие подходы к решению этого сценария? Какова рекомендуемая практика? Я спрашиваю об этом, потому что я не мог найти универсальное решение в любом месте в документах Android.
Ответы
Ответ 1
Некоторые сводки
Есть несколько методов, упомянутых выше, которые являются хорошими практиками, но я думал, что могу подвести их к кратким объяснениям. Ниже приведены некоторые из наиболее популярных библиотек, используемых в настоящее время для http-сетей, асинхронной работы/потоковой передачи и кэширования.
Мой текущий проект (только настройки)
В настоящее время я использую Отто, Loaders, Volley, Ormlite и сетевой стек на основе Apache и Service
s. Я надеюсь заменить сетевой стек в какой-то момент с помощью Volley, Retrofit и, возможно, в конечном итоге Robospice.
Я лично очень люблю Отто и Воллей.
RoboSpice (Modular)
- https://github.com/octo-online/robospice
- http://www.youtube.com/watch?v=ONaD1mB8r-A
- плагин/модульный подход к долгосрочным задачам
- Это похоже на "швейцарский армейский нож" библиотек, но вам нужно знать, что делает каждый инструмент.
- Обрабатывает вызовы REST
- сохраняет данные через ориентацию и другие изменения.
- может обрабатывать кэширование дисков и памяти)
- работает с различными библиотеками HTTP и библиотеками персистентности (Gson, Jackson, Spring, OkHttp и многими из нижеперечисленных библиотек)
- beta для поддержки Ormlite, я думаю
Дооснащение (REST)
Волейбол (сетевые данные и изображения)
Пикассо (изображения)
Погрузчики (Android)
- хорошо поддерживается
- сохраняются путем изменения ориентации и сохранения/загрузки состояния фрагмента.
- может быть трудно получить право
- нет кеширования
AsyncTask (Android)
- простой способ фоновой работы из потока пользовательского интерфейса.
- должен быть отменен и быть осторожным в отношении задач, которые возвращаются после того, как действие или фрагмент снесены.
Отто (шина событий)
- https://github.com/square/otto
- Шина событий, упрощающая синхронизацию между компонентами и фрагментами.
- Очень мощная способность
@Produce
сохраняет последнее событие и может производить его по требованию для любых новых заинтересованных абонентов на шине.
Безглавые фрагменты (?)
- Я лично никогда не видел, чтобы это использовалось иначе, чем Vogella tutorials, поэтому я не уверен в этом.
Сервис (Android)
- Старый школьный путь
- Конечный контроль, вы должны сделать все сами.
- обычно используется с клиентом Appache или HURL и
- пройти посылки по намерениям
Ответ 2
Почему бы вам не попробовать Loaders
, в частности AsyncTaskLoader
? Они доступны для предварительной сотовой связи через Support Library и идеально соответствуют жизненному циклу Activity/Fragment. Вот официальное резюме:
- Они доступны для каждой операции и фрагмента.
- Они обеспечивают асинхронную загрузку данных.
- Они отслеживают источник своих данных и предоставляют новые результаты при изменении содержимого.
- Они автоматически подключаются к последнему курсору загрузчика при воссоздании после изменения конфигурации. Таким образом, им не нужно повторно запрашивать свои данные.
Ответ 3
Фактически мы используем библиотеку RoboSpice. Он запускается в службе с предоставлением только объектов RequestListeners.
Проблема с вашим первым подходом (сохранение ссылок между AsyncTask) заключается в том, что вы, возможно, можете генерировать утечки памяти, потому что, когда ваши AsyncTasks содержат ваши ссылки на действия, они будут а не сбор мусора. Следите за этим только профилированием вашего приложения, проверяя размер кучи, который снова и снова повторял одно и то же действие. Ваша куча должна расти в нормальных параметрах (есть момент, когда ваши объекты, которые должны быть собраны в мусор, в одно и то же время связаны с новыми объектами), но когда GC запускает ваше распределение памяти, вы должны упасть до того же размера, который вы выделили на начало.
Итак, если мне нужно порекомендовать что-то, это будет следующее:
Активность управления вызовами API и потоками (с помощью RoboSpice, позволяя вращению UI)
Простые экраны внутри фрагментов с использованием функции keepInstance в true. Это позволит вам передавать свои DTO непосредственно вашим фрагментам, и вам нужно управлять состоянием только на самом высоком уровне.
Ответ 4
Если вы работаете с asyncTask, это ваша главная проблема: я не хочу загружать данные, каждый раз, когда меняется ориентация, вы можете попробовать это -
(1) Инициализировать любое значение до создания таким образом.
Boolean android_hacker = false;
(2) Теперь, когда вы закончите загрузку данных в классе AsyncTask, установите для этого значения значение true
android_hacker = true;
Здесь поддерживаются все данные, использующие модель и класс адаптера Array
(3) Теперь каждая временная ориентация изменяется, а затем проверяйте это как
if( android_hacker = true ){
// Use your saved instance ..
}else{
// Download data as it is yet not downloaded ..
}
Надеюсь, что это поможет.
Ответ 5
Есть много способов, которыми вы можете попробовать рядом с AsyncTask. И если вы попытаетесь найти наилучшую практику, AsyncTask - не лучший вариант. Этот ответ объясняет, почему вы не должны использовать AsyncTask. И они рекомендуют вам использовать лучший способ, который может работать с долговременной задачей, RoboSpice.
Я уже использовал эту библиотеку, и я думаю, что стоит попробовать: уважать действия lifecycles (изменение ориентации), не утечки памяти, поддерживает многопоточность, результаты кэшей... Он может подключать и отключать длительную задачу запроса, используя кеш (но он не может работать хорошо для запроса без кэша).
Но я рекомендую хороший путь от Google: IntentService
и BroadcastReceiver
. Вы будете регистрировать и незарегистрировать трансляцию во время изменения ориентации, чтобы получить результат данных. Вся фоновая задача будет работать в IntentService и уведомлять все, что вы хотите для деятельности BroadcastReceiver. Есть много примеров, которые вы можете попробовать. Что-то вроде этого: http://mobile.tutsplus.com/tutorials/android/android-fundamentals-intentservice-basics/
Обновление
Hi R4j, точка - мое приложение - тихий комплекс. И я должен сделать количество параллельных сетевых вызовов. Ваш подход с IntentService хорошо, но не подходит для сложных сценариев
Я не думаю, что это проблема. Вы можете делать что-либо с IntentService, даже сложные задачи. Если вам нужны параллельные задачи, вы можете рассмотреть Службу с многопотоковой обработкой в ней и общаться с активностью с помощью Intent. Передача намерений между Сервисом и активностью является безопасной и гибкой, то есть способом Android.
И если вы хотите кэшировать (по загрузке файла, потоку, по базе данных..) RoboSpice
- лучший выбор для вас
Ответ 6
Вы можете попробовать следующие подходы:
1) Если ваше приложение явно не требует каких-либо изменений ориентации, просто отключите изменения ориентации в начале выполнения приложения, таким образом, вы избежите любых сбоев или связанных с ними проблем в отношении изменений ориентации.
Это можно сделать, используя следующую строку в самом внешнем расположении вашего XML файла макета:
android:orientation="vertical"
(для установки вертикальной ориентации)
2) Вы можете установить или сохранить предыдущие значения ориентации в начале выполнения потока с помощью Asynctask, как показано ниже (только пример синтаксиса):
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
и
getResources().getConfiguration().orientation