Безопасно ли сохранять контекст приложения в статической переменной в Android?

Я знаю, что использование статических переменных в Android довольно рискованно, особенно если вы ссылаетесь на их действия. Однако, если у меня есть класс, который расширяет приложение (давайте назовем этот класс "приложением"), безопасно ли ссылаться на экземпляр этого класса?

Если да, то безопасно ли для любого другого класса иметь какую-либо ссылку на контекст приложения? Я имею в виду, может ли быть утечка памяти, если у меня есть ссылка на контекст приложения в каком-либо классе?

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

Кроме того, это не так важно, но если я буду использовать несколько процессов, получу ли я совершенно разные ссылки на класс App в каждом процессе?

В качестве примера кода, вот о чем я думаю:

public class App extends Application
{
    private static Context _appContext;

    @Override
    public void onCreate()
    {
        super.onCreate();
        _appContext = this;
    }

    public static Context getAppContext()
    {
        return _appContext;
    }
}

5 ответов

Решение

Безопасно ли сохранять контекст приложения в статической переменной?

В настоящее время, да, это кажется безопасным, хотя я бы не getAppContext() вернуть Context, а вместо этого вернуть App или же Application,

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

Как говорится в аббревиатуре, YMMV.:-)


РЕДАКТИРОВАТЬ

если да, то также безопасно для любого другого класса иметь какую-либо ссылку на контекст приложения?

Я понятия не имею, что вы подразумеваете под "безопасным" здесь.

но если я использую несколько процессов, я получу совершенно разные ссылки на класс App в каждом процессе, верно?

Если вы используете несколько процессов, вы должны получить по форели. Но да, вы должны стать отчетливым App экземпляров на процесс.

Это должно быть безопасно. Также следующее примечание из документации по API может иметь отношение к вам:

Обычно нет необходимости создавать подклассы Application, В большинстве случаев статические синглтоны могут предоставлять ту же функциональность более модульным способом. Если вашему синглтону нужен глобальный контекст (например, для регистрации широковещательных приемников), функции для его извлечения может быть задан контекст, который внутренне использует Context.getApplicationContext() при первом создании синглтона.

Это безопасно сделать в Application#onCreate() поскольку Application создается перед любой деятельностью. Если ваше приложение будет убито в фоновом режиме, Application Экземпляр будет воссоздан, и ваш глобальный будет установлен перед выполнением любого действия.

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

  1. Установить глобальный в активности A
  2. Перейдите к действию B
  3. Приложение уходит в фон
  4. Framework убивает приложение и процесс
  5. Приложение восстановлено
  6. Framework создает действие B. Действия в backstack не создаются до тех пор, пока вы не вернетесь к ним, поэтому глобальное не задано!
  7. Деятельность B пытается использовать глобальный, и бум... NullPointerException

Интересный комментарий появился в студии, когда я приводил в порядок неприятные статические контексты:

"Это утечка (которая также нарушает Instant Run)".

Итак, с запуском Instant Run у нас есть случай, когда разработчики Android не планируют сохранять статические переменные. Хотя мгновенный прогон (пока) не входит в мою повестку дня, полезно знать, что есть конкретный пример, где это не только плохая практика, но и случай использования, где он неправильный.

Это предупреждение при создании Context context; в андроид-студии:

Не размещайте контекстные классы Android в статических полях; это утечка памяти, которая также нарушает Instant Run.

Статическое поле будет пропускать контексты.

Нестатические внутренние классы имеют неявную ссылку на свой внешний класс.

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

Классы ViewModel никогда не должны указывать на представления или контексты вне приложения.

Другие вопросы по тегам