Передача ссылок на намерение действия

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

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

Как я уже сказал, довольно некрасиво. И нет такой вещи, как «myActivity.StartActivity(new Activity);». Все перегрузки для StartActivity принимают либо Intent, либо typeof(MyOtherActivity).

Итак, мой вопрос: я полностью неправильно понял концепцию действий или мне просто не хватает совершенно очевидного способа передачи им аргументов?

@Edit: причина, по которой я хочу передать фактическую ссылку на объект, а не просто копию объекта, заключается в том, что я пытаюсь передать модель представления из вышележащего действия в новое действие. И, конечно же, любые изменения, внесенные в эту модель представления, должны быть отражены в родительском действии, что будет возможно только в том случае, если модели представления двух действий указывают на один и тот же экземпляр.

Я пишу приложение с помощью Xamarin.Android, но код для C# и Java почти идентичен, поэтому ответы на любом из этих языков подходят.


person Falgantil    schedule 19.10.2015    source источник
comment
возможный дубликат stackoverflow.com/questions/2091465/   -  person dsharew    schedule 19.10.2015
comment
Частично верно. Ответы на ссылку, которую вы предоставили, отвечают, как переместить основные типы значений, такие как целые числа и строки, в отдельное действие, но не как передать фактический ссылочный объект, например объект моего собственного пользовательского типа.   -  person Falgantil    schedule 19.10.2015
comment
погуглил для вас. stackoverflow.com/questions/2736389/   -  person dsharew    schedule 19.10.2015
comment
Верно, но все эти результаты предлагают сделать его сериализуемым. Это означает, что я потеряю ссылку на объект. Именно это я и хочу сохранить. Другими словами, я хочу дать ему не объект, а ссылку на объект.   -  person Falgantil    schedule 19.10.2015
comment
Почему ты так хочешь? пожалуйста, обновите свой вопрос, указав причину.   -  person dsharew    schedule 19.10.2015
comment
Как насчет использования Fragments?   -  person Milen    schedule 20.10.2015


Ответы (2)


Проблема в том, что Android может в любой момент остановить процесс, в котором размещено ваше приложение (если он находится в фоновом режиме). Когда пользователь затем вернется в ваше приложение, Android создаст новый процесс для размещения вашего приложения и воссоздаст Activity в верхней части стека. Для этого Android хранит «сериализованную» версию Intent, чтобы он мог воссоздать Intent и передать его Activity. Вот почему все «дополнения» в Intent должны быть Parcelable или Serializable.

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

Еще один момент, который следует учитывать, заключается в том, что разные действия могут выполняться в разных процессах. Даже действия из одного и того же приложения могут находиться в разных процессах (если это указано в манифесте). Поскольку ссылки на объекты не работают за пределами процессов, это еще одна причина, по которой вы не можете передать ссылку на объект в файле Intent.

person David Wasser    schedule 19.10.2015
comment
Из того, что вы говорите, это звучит как невероятно нестабильная среда для создания приложений, учитывая, что вы никогда не знаете, какая часть вашего приложения работает, что затрудняет создание потока навигации, который не прерывается при выходе и повторном входе в приложение. в более поздний момент. Это правда? - person Falgantil; 19.10.2015
comment
Да, это правда. Это означает, что вам нужно спроектировать свое приложение с учетом этого. Вы не первый разработчик Android, столкнувшийся с этим, и не последний. - person David Wasser; 19.10.2015

Вы также можете использовать класс Application для глобального хранения объектов и их извлечения:

using Android.Runtime;

namespace SomeName
{
[Application]
public class App : Application
{
public string Name { get; set;}

public App (IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
{
}

public override void OnCreate ()
{
    base.OnCreate ();

    Name = "";
}
}
}

И вы можете получить доступ к данным с помощью:

App application = (App)Application.Context;
application.Name = "something";

Я решил сделать это в Application классе, потому что этот класс вызывается при запуске приложения, поэтому вам не нужно инициировать его вручную.
Имейте в виду, что переменные, которые относятся к Application, имеют свое время жизни, привязанное к приложению. по расширению.
Этот класс будет сборщиком мусора, если Android сочтет это необходимым, поэтому вам придется изменить код, чтобы включить и этот случай.
Вы можете использовать SharedPreferences или Database для сохранения ваших переменных на случай, если они получат удалять и извлекать их из класса App для более быстрого получения результатов.

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

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

И не забывайте освобождать ресурсы по мере необходимости на OnStop и OnDestroy
Я редко использую намерения, мне так удобнее.

person CDrosos    schedule 19.10.2015
comment
Это то, что имел в виду ОП, когда говорил об использовании статических переменных. Для этого вам не нужен класс Application, вы можете просто использовать статические переменные. ОП ищет более элегантное решение ;-) - person David Wasser; 19.10.2015
comment
кто такой ОП? :) , с классом приложения вы можете сделать персонал и быть уверенным, что это будет сделано с начала приложения до конца. Почему это решение не элегантно? какое решение может быть элегантным? встроенная поддержка Android для глобальных переменных? - person CDrosos; 19.10.2015
comment
На правильном пути ошибка, просто некоторая справочная информация о том, почему это немного изменчиво ... Ваш процесс может быть остановлен ОС в любое время (например: активность какое-то время была фоновой, высокая нагрузка на память из других приложений и т. д.), класс Application может быть снесен и воссоздан без вашего ведома. Свойство Name в этом случае будет сброшено; улучшенным решением было бы сохранить его в общих настройках через геттер и сеттер или восстановить объекты через базу данных. - person matthewrdev; 20.10.2015
comment
@matthewrdev вы были правы, я ничего не говорил об этой возможности, я отредактировал ответ с дополнительной информацией, и я считаю, что теперь это гораздо лучший ответ. - person CDrosos; 21.10.2015