Страницы

Поиск по вопросам

понедельник, 25 ноября 2019 г.

К чему может привести использование static переменных?


Всем добрый вечер.
В процессе разработки приложения есть большая необходимость передачи каких либо переменных из одной Активити в другую. Я использовал всегда стандартный метод:
Intent intent = new Intent(First.this, Second.class);
intent.putExtra("key",from_to);
startActivity(intent);

И далее получение:
String from_to = getIntent().getExtras().getString("key", "null");

Но данный метод мне откровенно осточертел, и я решил делать это через static преременные так:
static String from_to;

Где то:
from_to = "Hello dear Android";

И в другой активити:
String from_to = First.from_to;

Но теперь меня мучает вопрос: чем же это может обернуться для меня?!
Заранее всем спасибо!    


Ответы

Ответ 1



Половина из написанного откровенная чушь не совсем верна. Если все делат по человечачьи то ужасов навроде #сборщикмусораубил или #нарвалсянаnullpointer можно избежать. В Android есть такой класс Application, который является естественным синглтоном. Как пишется в умной книжке: When your Application implementation is registered in the manifest, it will be instantiated when your application process is created. As a result your Application implementation is by nature a singleton and should be implemented as such to provide access to its methods and member variables. Надо всего лишь создать свой собственный Application типа: public class MyApplication extends Application { private static MyApplication singleton; private static MyVar myPreciousStaticVariable; // Returns the application instance public static MyApplication getInstance() { return singleton; } public final void onCreate() { super.onCreate(); singleton = this; } } Правильно задекларировать в манифесте и вперед. Нужные статические переменные (без фанатизма - то есть за минусом контекстов, юа элементов и проч. сумасшедшины) пихаем в MyApplication с правильной инициализацией в Application.onCreate() или в конструкторе (не забываем про lazy-init!), обкладываем статику геттерами (при необходимости и сеттерами) и все. Далее в более менее любом месте проги делаем так: myVar=MyApplication.getInstance().getMyPreciousStaticVariable(); Update С освобождением ресурсов в Application это действительно проблема. Поскольку в Applicatio нет явного колбэка вызываемого при закрытии. Немного утешает, что Application создаетс еще до момента создания любой из компонент приложения - Activity, Service, Receive и проч. так что вы не сможете в Application явным образом создать эти объекты. А обще правило при создании объекта гласит - уничтожай там же где и создал. Так что создаем скажем в Activity.onCreate() - стало быть уничтожаем в Activity.onDestroy() и т.д. В общем хранение синглтон объектов в Application имеет свои ограничения - я согласен. В любом случае Application будет выгружен последним и все что останется после него будет убрано сборщиком мусора - не совсем кошерно, конечно.

Ответ 2



обернется NullPointerException в тот прекрасный момент, когда приложение полность выгрузится из памяти и будет открыто вновь (например, свернуто кнопкой "Домой" и открыто из списка последних запущенных). допустим такая ситуация: в Activity_A есть статичное поле, в Activity_B оно используется. текущий стек тако Activity_A -> Activity_B. приложение выгрузилось из памяти, все ссылки на объекты включая статичные поля, были обнулены. Приложение восстанавливается из памяти, первой будет загружена Activity_B (поскольку она на вершине стека), которая обращается к статичному полю в Activity_A, и тут же получает NullPointerException. Надеюсь понятно описал. как раз-таки способ передачи через Intent более предпочтителен, поскольку все переданны параметры будут сохранены вместе с состоянием текущей активности и будут так же восстановлены.

Ответ 3



Как минимум утечкой памяти. Поясняю. Интернированные строки хранятся не в heapspace, а в permgen space. Сборка мусор в нем происходит по отдельным правилам, не так как в heap-e / young /tenured memory pools. Сборщик мусора в Java не является универсальным механизмом, позволяющим программист полностью забыть о правилах использования памяти и о том, в каких случаях осуществляется его работа. Статичная переменная хранится своим классом, а как следствие, его загрузчиком (classloader) По причине внешнего использования увеличивается шанс, что сборщик мусора не соберё данный экземпляр. Также зачастую в static-переменных кэшируется информация или же хранятся состояния, используемые несколькими потоками. Отдельным примером являются статичные коллекции. Хорошим же тоном при архитектурном проектировании служит полное избегание изменяемых статичных объектов — зачастую существует лучшая альтернатива.

Ответ 4



Тема старая, но всегда актуальная. Все ответы хороши, но забыт один довольно редкий случай, когда части приложения запущены в разных процессах. Теория здесь: https://developer.android.com/guide/components/processes-and-threads.html Так вот в случае межпроцессной коммуникации никакие статические переменные не помогут В новом процессе загрузится класс по новому и все статические поля будут пустыми. И только Intent + Bundle + Parcelable вам смогут доставить данные в новый/иной процесс.

Комментариев нет:

Отправить комментарий