У меня есть одно действие, которое является основным действием, используемым в приложении, и оно имеет ряд переменных. У меня есть два других занятия, которые я хотел бы использовать, используя данные первого занятия. Теперь я знаю, что могу сделать что-то вроде этого:
GlobalState gs = (GlobalState) getApplication();
String s = gs.getTestMe();
Однако я хочу поделиться многими переменными, и некоторые из них могут быть довольно большими, поэтому я не хочу создавать их копии, как описано выше.
Есть ли способ напрямую получить и изменить переменные без использования методов get и set? Я помню, как читал статью на сайте разработчиков Google, в которой говорилось, что это не рекомендуется для производительности на Android.
Ответы:
Вот подборка самых распространенных способов добиться этого :
WeakReferences
TL; DR : существует два способа обмена данными: передача данных в дополнениях к цели или сохранение их в другом месте. Если данные являются примитивами, строками или объектами, определенными пользователем: отправьте их как часть дополнений к намерениям (объекты, определенные пользователем, должны быть реализованы
Parcelable
). При передаче сложных объектов сохраняйте экземпляр в одном месте где-нибудь еще и получайте к ним доступ из запущенного действия.Некоторые примеры того, как и зачем реализовывать каждый подход:
Отправить данные в намерениях
На втором занятии:
Используйте этот метод, если вы передаете примитивные данные или строки . Вы также можете передавать объекты, которые реализует
Serializable
.Несмотря на соблазн, вы должны подумать дважды перед использованием
Serializable
: это подвержено ошибкам и ужасно медленно. Итак, в целом: держитесь подальше,Serializable
если это возможно. Если вы хотите передать сложные пользовательские объекты, взгляните наParcelable
интерфейс . Его сложнее реализовать, но он значительно выиграл в скоростиSerializable
.Обмен данными без сохранения на диске
Можно обмениваться данными между действиями, сохраняя их в памяти, учитывая, что в большинстве случаев обе операции выполняются в одном и том же процессе.
Примечание: иногда, когда пользователь покидает вашу деятельность (не выходя из нее), Android может решить убить ваше приложение. В таком сценарии у меня были случаи, когда андроид пытается запустить последнее действие, используя намерение, предоставленное до того, как приложение было убито. В этом случае данные, хранящиеся в единственном экземпляре (как вашем, так и
Application
), исчезнут, и могут случиться плохие вещи. Чтобы избежать таких случаев, вы либо сохраняете объекты на диск, либо проверяете данные перед их использованием, чтобы убедиться, что они действительны.Используйте одноэлементный класс
Есть класс для хранения данных:
Из запущенной деятельности:
Используйте приложение синглтон
Синглтон приложения - это экземпляр,
android.app.Application
который создается при запуске приложения. Вы можете предоставить пользовательский, расширивApplication
:Перед началом деятельности:
Тогда из запущенной деятельности:
Статические поля
Идея в основном такая же, как у синглтона, но в этом случае вы предоставляете статический доступ к данным:
Из запущенной деятельности:
HashMap из
WeakReferences
Та же идея, но позволяющая сборщику мусора удалять объекты, на которые нет ссылок (например, когда пользователь завершает действие):
Перед началом деятельности:
Из запущенной деятельности:
Вы можете или не можете передавать идентификатор объекта, используя дополнительные функции намерения. Все зависит от вашей конкретной проблемы.
Сохранять объекты на диске
Идея состоит в том, чтобы сохранить данные на диске перед запуском другого действия.
Преимущества: вы можете запустить действие из других мест и, если данные уже сохранены, оно должно работать просто отлично.
Недостатки: это громоздко и требует больше времени для реализации. Требуется больше кода и, следовательно, больше шансов на появление ошибок. Это также будет намного медленнее.
Вот некоторые из способов сохранения объектов:
источник
setResult
метода. Кроме того, в этом случае вторичная активность должна вызываться с использованиемstartActivityForResult
метода.Activity
всех иonCreate()
проверяйте любое статическое поле синглета, которое вы заполняете при запуске приложения. Если это поле пустое, вернитесь к началу действия, используяFLAG_ACTIVITY_CLEAR_TASK
или,BroadcastReceiver
чтобы убить другие действия.Что вы можете использовать:
То, что вы выбираете, зависит от ваших потребностей. Вероятно, вы будете использовать более одного способа, когда у вас есть "много"
источник
MAIN
действия. После завершения процесса вы перезапускаете все действия, которые были открыты последними, что может быть страницей с подробностями где-то глубоко в приложении.Делайте то, что Google приказывает вам делать! здесь: http://developer.android.com/resources/faq/framework.html#3
источник
Это не делает копию (особенно со String , но даже объекты передаются по значению ссылки, а не самому объекту, и подобный метод получателя подходит для использования - возможно, лучше использовать, чем другие средства, потому что они распространены и хорошо понимал). Старые «мифы о производительности», такие как не использование геттеров и сеттеров, все еще имеют некоторую ценность, но также были обновлены в документах .
Но если вы не хотите этого делать, вы также можете просто сделать переменные общедоступными или защищенными в GlobalState и получить к ним доступ напрямую. И вы можете сделать статический синглтон, как указывает объект приложения JavaDoc :
Использование данных Intent , как отмечают другие ответы, - это еще один способ передачи данных, но обычно он используется для небольших данных и простых типов. Вы можете передавать большие / более сложные данные, но они более сложны, чем просто использование статического одиночного кода. Тем не менее, объект « Приложение» все еще является моим личным фаворитом для совместного использования больших / более сложных непостоянных данных между компонентами приложения Android (поскольку в приложении Android он имеет четко определенный жизненный цикл).
Кроме того, как уже отмечали другие, если данные становятся очень сложными и должны быть постоянными, то вы также можете использовать SQLite или файловую систему.
источник
Вы можете расширить класс Application и пометить любые объекты там, где вы хотите, они будут доступны в любом месте вашего приложения
источник
Существует новый и лучший способ обмена данными между действиями, это LiveData . Обратите внимание, в частности, на эту цитату со страницы разработчика Android:
Смысл этого огромен - любые данные модели могут быть разделены в общем одноэлементном классе внутри
LiveData
оболочки. Это может быть введено из действий в их соответствующиеViewModel
для тестируемости. И вам больше не нужно беспокоиться о слабых ссылках, чтобы предотвратить утечки памяти.источник
Использование хэш-карты подхода со слабыми ссылками, описанного выше, и в http://developer.android.com/guide/faq/framework.html мне кажется проблематичным. Как восстанавливаются целые записи, а не только значение карты? В какой сфере вы выделяете это? Поскольку инфраструктура контролирует жизненный цикл Деятельности, владение одним из участвующих Мероприятий может привести к ошибкам во время выполнения, когда владелец уничтожается заранее перед своими клиентами. Если приложению принадлежит его, некоторое действие должно явно удалить запись, чтобы хеш-таблица не удерживала записи с действительным ключом и потенциально собранной слабой ссылкой. Кроме того, что должен делать клиент, когда значение, возвращаемое для ключа, является нулевым?
Мне кажется, что WeakHashMap, принадлежащий приложению или в пределах одного экземпляра, является лучшим выбором. Доступ к значению на карте осуществляется через ключевой объект, и когда нет строгих ссылок на ключ (т. Е. Все действия выполняются с ключом и тем, на что он отображается), GC может восстановить запись карты.
источник
Существуют различные способы обмена данными между действиями.
1: Передача данных между действиями с использованием Intent
2: Используя ключевое слово static, определите переменную как public static и используйте любое место в проекте
использовать в любом месте проекта, используя classname.variableName;
3: Использование базы данных
но процесс занимает немного больше времени, вы должны использовать запрос для вставки данных и повторять данные с помощью курсора, когда это необходимо. Но нет шансов потерять данные без очистки кеша.
4: Использование общих настроек
намного проще, чем база данных. но есть некоторые ограничения: вы не можете сохранять объекты ArrayList, List и custome.
5: Создайте установщик геттера в классе Aplication и получите доступ к любой точке проекта.
здесь установить и получить от деятельности
источник
Ну, у меня есть несколько идей, но я не знаю, являются ли они тем, что вы ищете.
Вы можете использовать службу, которая содержит все данные, а затем просто связать свои действия со службой для извлечения данных.
Или упакуйте свои данные в сериализуемый или пакетный и прикрепите их к пакету и передайте пакет между действиями.
Это может быть совсем не то, что вы ищете, но вы также можете попробовать использовать SharedPreferences или предпочтение в целом.
В любом случае, дайте мне знать, что вы решите.
источник
Предполагая, что вы вызываете действие два из действия одно, используя намерение.
Вы можете передать данные с помощью intent.putExtra (),
Возьмите это для справки. Отправка массивов с помощью Intent.putExtra
Надеюсь, это то, что вы хотите.
источник
Если вы собираетесь вызывать другие действия из текущего действия, вы должны использовать Intents . Вы можете сосредоточиться не столько на сохранении данных, сколько на обмене по мере необходимости.
Однако, если вам действительно нужно сохранить эти значения, вы можете сохранить их в каком-либо структурированном текстовом файле или базе данных в локальном хранилище. Файл свойств, файл XML или файл JSON могут хранить ваши данные и могут быть легко проанализированы при создании действия. Не забывайте также, что у вас есть SQLite на всех устройствах Android, чтобы вы могли хранить их в таблице базы данных. Вы также можете использовать Map для хранения пар ключ-значение и сериализации карты в локальное хранилище, но это может быть слишком громоздким, чтобы быть полезным для простых структур данных.
источник
Все вышеупомянутые ответы великолепны ... Я просто добавляю еще один, о котором никто еще не упомянул, о сохранении данных посредством действий, а именно об использовании встроенной базы данных SQLite для Android для сохранения соответствующих данных ... Фактически вы можете разместить databaseHelper в состоянии приложения и вызывайте его по мере необходимости во время активации. Или просто создайте вспомогательный класс и, при необходимости, выполняйте вызовы БД ... Просто добавьте еще один слой для рассмотрения ... Но всех остальных ответов будет достаточно как хорошо .. на самом деле просто предпочтение
источник
Пример обмена данными между активами. Пример передачи электронного письма после входа в систему.
«email» - это имя, которое можно использовать для ссылки на значение запрашиваемой активности
1 код на странице входа
2 код на главной странице
источник
И если вы хотите работать с объектом данных, эти две реализации очень важны:
Сериализуемый против Parcelable
public class User implements Parcelable
проверьте больше здесь
источник