Как объявить глобальные переменные в Android?

javadoc класса File описывает класс как:

Абстрактное представление имен файлов и каталогов.

File - это только представление пути, с несколькими методами, относящимися к файловой системе (например, exists()) и обработкой каталога, но фактические потоковые ввод и вывод выполняются в другом месте. Потоки можно открывать и закрывать, файлы не могут.

(Мое личное мнение заключается в том, что довольно неудачно, что Sun затем создала RandomAccessFile, вызывая много путаницы с его непоследовательным наименованием.)

588
задан Willi Mentzel 3 January 2017 в 13:55
поделиться

4 ответа

Я записал, что это огрызается в '09, когда Android был относительно новым, и были многие не хорошо установленные области в разработке Android. Я добавил длинное приложение в нижней части этого сообщения, обратившись к некоторой критике, и детализировав философское разногласие, которое я имею с использованием Одиночных элементов вместо того, чтобы разделить Приложение на подклассы. Считайте его на Ваш собственный риск.

ИСХОДНЫЙ ОТВЕТ:

Более общая проблема, с которой Вы встречаетесь, состоит в том, как сохранить состояние через несколько Операций и все части Вашего приложения. Статическая переменная (например, одиночный элемент) является общим Java способ достигнуть этого. Я нашел однако, что более изящный путь в Android состоит в том, чтобы связать Ваше состояние с контекстом Приложения.

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

Способ сделать это должно создать Ваш собственный подкласс android.app. Приложение, и затем указывает что класс в теге приложения в Вашей декларации. Теперь Android автоматически создаст экземпляр того класса и сделает его доступным для Вашего целого приложения. Можно получить доступ к нему от любого context использование Context.getApplicationContext() метод (Activity также предоставляет метод getApplication() который имеет тот же самый эффект). Следующее является чрезвычайно упрощенным примером с протестами следовать:

class MyApp extends Application {

  private String myState;

  public String getState(){
    return myState;
  }
  public void setState(String s){
    myState = s;
  }
}

class Blah extends Activity {

  @Override
  public void onCreate(Bundle b){
    ...
    MyApp appState = ((MyApp)getApplicationContext());
    String state = appState.getState();
    ...
  }
}

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

Что-то для замечания в примере выше; предположите, что мы вместо этого сделали что-то как:

class MyApp extends Application {

  private String myState = /* complicated and slow initialization */;

  public String getState(){
    return myState;
  }
}

Теперь эта медленная инициализация (такая как совершающий нападки диск, поражая сеть, что-либо блокирование, и т.д.) будет выполнена каждый раз, когда Приложение инстанцируют! Можно ли думать, ну, в общем, что это только однажды для процесса, и я должен буду оплатить стоимость так или иначе, правильно? Например, как Dianne Hackborn упоминает ниже, для Вашего процесса совершенно возможно быть инстанцированным - только для обработки фонового многоадресного события. Если Ваша широковещательная обработка не имеет никакой потребности в этом состоянии, Вы потенциально только что сделали целый ряд сложных и медленных операций ни для чего. Ленивое инстанцирование является названием игры здесь. Следующее является немного более сложным способом использовать Приложение, которое имеет больше смысла для чего-либо кроме самого простого из использования:

class MyApp extends Application {

  private MyStateManager myStateManager = new MyStateManager();

  public MyStateManager getStateManager(){
    return myStateManager ;
  }
}

class MyStateManager {

  MyStateManager() {
    /* this should be fast */
  }

  String getState() {
    /* if necessary, perform blocking calls here */
    /* make sure to deal with any multithreading/synchronicity issues */

    ...

    return state;
  }
}

class Blah extends Activity {

  @Override
  public void onCreate(Bundle b){
    ...
    MyStateManager stateManager = ((MyApp)getApplicationContext()).getStateManager();
    String state = stateManager.getState();
    ...
  }
}

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

ПРИМЕЧАНИЕ 1: Также как антикафе прокомментировало для корректной связи переопределения Приложения с приложением, тег необходим в файле манифеста. Снова, см. документы Android для большего количества информации пример:

<application
     android:name="my.application.MyApp" 
     android:icon="..."
     android:label="...">
</application>

ПРИМЕЧАНИЕ 2: user608578 спрашивает ниже, как это работает с руководящими собственными объектными жизненными циклами. Я не до скорости при использовании собственного кода с Android в малейшем, и я не квалифицирован, чтобы ответить, как это взаимодействовало бы с моим решением. Если у кого-то действительно есть ответ на это, я готов кредитовать их и поместить информацию в это сообщение для максимальной видимости.

ПРИЛОЖЕНИЕ:

Как некоторые люди отметили, это не решение для постоянного состояния, что-то, что я, возможно, должен был подчеркнуть больше в исходном ответе. Т.е. это не предназначено, чтобы быть решением для сохранения пользователя или другой информации, которая предназначена, чтобы быть сохраненной через время жизни приложения. Таким образом я считаю большую часть критики ниже связанного с Приложениями уничтоженной в любое время, и т.д...., спорный, как что-либо, что когда-либо должно было сохраняться к диску, не должен быть сохранен через подкласс Приложения. Это предназначено, чтобы быть решением для хранения временного, легко re-creatable состояние приложения (зарегистрирован ли пользователь, например), и компоненты, которые являются единственным экземпляром (менеджер по сети приложения, например) (НЕ одиночный элемент!) по своей природе.

Dayerman был достаточно любезен для указания на интересный разговор с Reto Meier и Dianne Hackborn, в которой использованию подклассов Приложения препятствуют в пользу Шаблонов "одиночка". Somatik также указал на что-то вроде этой природы ранее, хотя я не видел его в то время. Из-за Reto и ролей Dianne в поддержании платформы Android, я не могу добросовестно рекомендовать игнорировать их совет. То, что они говорят, идет. Я действительно хочу не согласиться с мнениями, выраженными относительно предпочтения Singleton по подклассам Приложения. В моем разногласии я буду использовать понятия, лучше всего объясненные в этом объяснении StackExchange шаблона разработки Singleton, так, чтобы я не определял условия в этом ответе. Я высоко поощряю просматривать ссылку перед продолжением. Детально:

Состояния Dianne, "Нет никакой причины разделить на подклассы из Приложения. Это не отличается, чем создание одиночного элемента..." Это первое требование является неправильным. Существует две главных причины для этого. 1) Класс приложений предоставляет лучшую пожизненную гарантию разработчику приложений; это, как гарантируют, будет иметь время жизни приложения. Одиночный элемент ЯВНО не связывается со временем жизни приложения (хотя это эффективно). Это может быть надуманным вопросом для Вашего среднего разработчика приложений, но я утверждал бы, что это - точно тип контракта, который должен предлагать API Android, и он предоставляет намного больше гибкости системе Android также путем уменьшения времени жизни связанных данных. 2) Класс приложений предоставляет разработчику приложений единственного держателя экземпляра для состояния, которое очень отличается от держателя Singleton состояния. Для списка различий посмотрите, что объяснение Singleton связывается выше.

Dianne продолжает, "... просто, вероятно, чтобы быть чем-то Вы сожалеете в будущем, поскольку Вы находите свой Объект приложения, становящийся этой большой запутанной путаницей того, что должно быть логикой независимого приложения". Это, конечно, весьма корректно, но это не причина выбора подкласса Singleton over Application. Ни один из аргументов Diane не обеспечивает причину, что использование Singleton лучше, чем подкласс Приложения, все, что она пытается установить, то, что использование Singleton не хуже, чем подкласс Приложения, которому я верю, ложь.

Она продолжает, "И это приводит более естественно к тому, как необходимо управлять этими вещами - инициализация их по требованию". Это игнорирует то, что нет никакой причины, Вы не можете инициализировать по требованию использование подкласса Приложения также. Снова нет никакого различия.

Концы Dianne с самой "Платформой имеют тонны и тонны одиночных элементов для весь, мало обменялось данными, это поддерживает для приложения, такого как кэши загруженных ресурсов, пулы объектов, и т.д. Это работает отлично". Я не утверждаю, что использование Одиночных элементов не может хорошо работать или не является законной альтернативой. Я утверждаю, что Одиночные элементы не предоставляют столь же сильный контракт с системой Android как использование подкласса Приложения, и далее что использование Одиночных элементов обычно указывает на негибкий дизайн, который легко не изменяется и приводит ко многим проблемам в будущем. По моему скромному мнению, сильный контракт, который API Android предлагает приложениям разработчика, является одним из самых привлекательных и приятных аспектов программирования с Android и помог привести к раннему принятию разработчиками, которое управляло платформой Android к успеху, который это имеет сегодня. Предложение Одиночных элементов использования неявно переезжает от сильного контракта API, и по-моему, ослабляет платформу Android.

Dianne прокомментировала ниже также, упомянув дополнительную оборотную сторону использованию подклассов Приложения, они могут поощрить или помочь написать меньше кода производительности. Это очень верно, и я отредактировал этот ответ для подчеркивания важности рассмотрения перфекта здесь и проявления корректного подхода, если Вы используете разделение на подклассы Приложения. Как Dianne заявляет, важно помнить, что Ваш Класс приложений инстанцируют каждый раз, когда Ваш процесс загружается (мог быть многократно сразу если Ваше выполнение приложения в нескольких процессах!), даже если процесс только загружается для фонового многоадресного события. Поэтому важно использовать Класс приложений больше в качестве репозитория для указателей на совместно используемые компоненты Вашего приложения, а не как место, чтобы сделать любую обработку!

Я оставляю Вас со следующим списком оборотных сторон к Одиночным элементам, как украдено от более ранней ссылки StackExchange:

  • Неспособность использовать абстрактные или интерфейсные классы;
  • Неспособность разделить на подклассы;
  • Высоко связываясь через приложение (трудный изменить);
  • Трудный протестировать (не может фальсифицировать/дразнить в модульных тестах);
  • Трудный параллелизировать в случае изменяемого состояния (требует обширной блокировки);

и добавьте мое собственное:

  • Неясный и неуправляемый пожизненный контракт, неподходящий для Android (или большинство другой) разработка;
952
ответ дан 22 November 2019 в 22:02
поделиться

У Вас может быть статическое поле для хранения этого вида состояния. Или помещенный это в Пакет ресурса и восстановление оттуда на onCreate (Связывают savedInstanceState). Просто удостоверьтесь, что Вы полностью понимаете, что приложение для Android управляло жизненным циклом (например, почему к входу в систему () обращаются изменение ориентации клавиатуры).

3
ответ дан 22 November 2019 в 22:02
поделиться

Я не мог найти, как указать тег приложений, но после многих Googling он стал очевидным из файлов файлов манифеста: используйте Android: Name, в дополнение к значке по умолчанию и метку в приложении STANZA.

Android: имя Полное название подкласса приложений, реализованное для приложения. Когда процесс приложения запускается, этот класс создается до каких-либо компонентов приложения.

Подкласс является необязательным; Большинство приложений не понадобятся. В отсутствие подкласса Android использует экземпляр класса Base Application.

13
ответ дан 22 November 2019 в 22:02
поделиться

Создайте этот подкласс

public class MyApp extends Application {
  String foo;
}

В AndroidManifest.xml добавьте android: name

Пример

<application android:name=".MyApp" 
       android:icon="@drawable/icon" 
       android:label="@string/app_name">
153
ответ дан 22 November 2019 в 22:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: