Зачем расширять класс приложений Android?

168

Расширенный Applicationкласс может объявлять глобальные переменные. Есть ли другие причины?

TN888
источник
Это всего лишь идея из головы, но вы должны иметь возможность переопределить onCreate и показать однократный экран запуска, а не MainActivity, то есть экран вступления при первом запуске приложения пользователем.
13

Ответы:

29

Я не могу придумать реальный сценарий, в котором расширение Application либо предпочтительнее другого подхода, либо необходимо для достижения чего-либо. Если у вас есть дорогой, часто используемый объект, вы можете инициализировать его в IntentService, когда обнаружите, что объект в данный момент отсутствует. Само приложение работает в потоке пользовательского интерфейса, а IntentService - в своем собственном потоке.

Я предпочитаю передавать данные из Activity в Activity с явным Intents или использовать SharedPreferences. Существуют также способы передачи данных из фрагмента в его родительское действие с использованием интерфейсов.

Джо Малин
источник
39
Существует множество способов расширения класса приложения. Одним из очень полезных является перехват всех необработанных исключений в вашем приложении. Так что это то, что может быть очень удобно
PNG
3
Как ты это делаешь ?
Серж
8
+1 за "prefer to pass data from Activity to Activity with explicit Intents, or use SharedPreferences". Мы всегда должны как можно больше устранять глобальное состояние и использовать стандартные инструменты Android для управления глобальным состоянием вместо статических переменных / синглетонов и т. Д.
Александр Караберов
9
Зачем? подготовиться к Android в какой-то момент, запустив их в разных процессах или в любом другом и повторно используемом компоненте, хотя это намеренно ограничено? просто передача объектов данных вместо их сериализации экономит процессор и память. распределение ресурсов для передачи обслуживания внутри процесса на одном устройстве не является идеальным в любом случае. Я действительно не вижу смысла использования intentservice таким образом (просто создайте другой поток с новым). действительно много вещей, которые сбивают с толку программистов, происходит из-за того, что почти все добавленные в Google «помощники» сделаны так, как будто действия выполнялись на разных компьютерах.
Ласси Киннунен
127

Введение:

введите описание изображения здесь

  1. Если мы рассмотрим apkфайл на нашем мобильном телефоне, он состоит из нескольких полезных блоков, таких как, Activitys, Services и другие.
  2. Эти компоненты не общаются друг с другом регулярно и не забывают, что имеют свой жизненный цикл. которые указывают, что они могут быть активными в одно время и неактивными в другой момент.

Требования:

  1. Иногда нам может потребоваться сценарий, в котором нам нужен доступ к переменной и ее состояниям во всем, Applicationнезависимо от того, какой Activityпользователь использует,
  2. Примером является то, что пользователю может потребоваться доступ к переменной, которая содержит информацию о его персонале (например, имя), которая должна быть доступна через Application,
  3. Мы можем использовать SQLite, но создание Cursorи закрытие его снова и снова не сказывается на производительности,
  4. Мы могли бы использовать Intents для передачи данных, но это неуклюже, и сама активность может не существовать при определенном сценарии в зависимости от доступности памяти.

Использование класса приложения:

  1. Доступ к переменным по всему Application,
  2. Вы можете использовать Applicationдля запуска определенных вещей, таких как аналитика и т. Д., Так как класс приложения запускается перед запуском Activitys или Servicess,
  3. Существует переопределенный метод onConfigurationChanged (), который запускается при изменении конфигурации приложения (с горизонтального на вертикальное и наоборот),
  4. Существует также событие onLowMemory (), которое запускается, когда на устройстве Android недостаточно памяти.
Devrath
источник
В вашей части требований, почему бы не использовать SharedPreferences?
В первом примере, например, для сохранения личной информации, может использоваться SharedPreferences. Но примеры, которые вы привели в последней части, сняли мои сомнения. Спасибо!
Саурабх Сингх
63

Класс приложения - это объект, который имеет полный жизненный цикл вашего приложения. Это ваш самый высокий уровень в качестве приложения. пример возможного использования:

  • Вы можете добавить то, что вам нужно при запуске приложения, переопределив onCreate в классе Application.

  • хранить глобальные переменные, которые переходят из Activity в Activity. Нравится Asynctask.

    и т.д

wtsang02
источник
4
Использование Application в качестве полигона для глобальных переменных приложения - большой запах кода. Вы должны использовать свои собственные, более специфичные классы как одиночные или со статическими переменными, чтобы сделать это.
Остин
5
@ Остин, почему это запах?
Relm
1
Да, зачем пахнуть? Как указывалось ранее, класс Application находится на вершине иерархии, и я могу поспорить, что мои деньги на ланч находятся ниже, чем пользовательский класс синглтона. Таким образом, если нажать кнопку толчка, а на вашем телефоне недостаточно памяти, я бы сказал, что убит пользовательский синглтон, а не класс Application (по сути, ваше целое приложение).
Starwave
31

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

Например, если вы хотите получить базовые данные аутентификации для каждого http- запроса, вы можете реализовать методы для данных аутентификации в объекте приложения.

После этого вы можете получить имя пользователя и пароль в любом из следующих действий:

MyApplication mApplication = (MyApplication)getApplicationContext();
String username = mApplication.getUsername();
String password = mApplication.getPassword();

И, наконец, не забудьте использовать объект Application в качестве одноэлементного объекта:

 public class MyApplication extends Application {
    private static MyApplication singleton;

    public MyApplication getInstance(){
        return singleton;
    }
    @Override
    public void onCreate() {
        super.onCreate();
        singleton = this;
    }
}

Для получения дополнительной информации, пожалуйста, нажмите Application Class

IntelliJ Amiya
источник
2
пожалуйста, объясните мне, почему нам нужно явно сделать одноэлементный объект класса Application, насколько я знаю, он сам является одноэлементным. Можем ли мы сделать несколько объектов приложения, если сможем, то как? и каковы последствия? Пожалуйста, объясните.
Сайед Раза Мехди
Нет, вероятно, только один класс приложения. developer.android.com/guide/topics/manifest/...
IntelliJ Amiya
тогда почему нам нужно явно поддерживать его одноэлементный объект? Разве ОС не поддерживает это для нас? На самом деле я столкнулся с кодом, в котором есть объект приложения, созданный в классе деятельности, и он не упоминается в манифесте. Я думаю, что это неправильно, также мне любопытно, почему мы делаем статический одноэлементный объект. То, что вы считаете лучшим подходом. Спасибо за ответ.
Сайед Раза Мехди
1
спасибо, я нашел ответ здесь по этой ссылке developer.android.com/reference/android/app/Application.html
Syed Raza Mehdi
Где находится * одиночный * объект в этом
доктор АНДРО
8

Класс Application - это одноэлементный объект, к которому вы можете получить доступ из любого действия или из любого другого места, где у вас есть объект Context.

Вы также получаете немного жизненного цикла.

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

Джон Ф Хэнкок
источник
6
«Вы также получаете немного жизненного цикла». Вы можете перефразировать это.
wtsang02
2
Я имею в виду, что вы получаете несколько вызовов жизненного цикла, но не столько, сколько с действием или фрагментом. Например, нет класса onDestroy () для класса Application.
Джон Ф Хэнкок
Этот класс создан автоматически?
Константин Конопко
Да. До тех пор, пока вы правильно указали в AndroidManifest.xml.
Джон Ф Хэнкок
Нет, он не создается автоматически. Вы должны создать его, а затем объявить его в файле манифеста
Ojonugwa Jude Ochalifu
7

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

public class BaseJuiceApplication extends Application implements BootListener {

    public static BaseJuiceApplication instance = null;

    public static Context getInstance() {
        if (null == instance) {
            instance = new BaseJuiceApplication();
        }
        return instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();


    }

    @Override
    public void onBootCompleted(Context context, Intent intent) {
        new PushService().scheduleService(getInstance());
        //startToNotify(context);
    }
Сришти Рой
источник
Мне интересно, почему нам нужно сделать статическую ссылку на объект приложения, где, как мы можем получить его с помощью getApplication () и типизировать его к классу приложения. Насколько я понял эту концепцию, класс приложений создается самой ОС, и он должен иметь только один экземпляр, поддерживаемый ОС. Пожалуйста, объясните, спасибо.
Сайед Раза Мехди
Ты прав. Вызов getApplication из любого компонента приложения в вашем приложении возвращает единственный производный от приложения экземпляр, который является вашим приложением. Это обрабатывается внутри платформы Android. Все, что вам нужно сделать, это привести этот возвращенный экземпляр к вашему пользовательскому классу, который расширяет Application. Вам также необходимо соответствующим образом настроить манифест, чтобы в экземпляре Android использовался соответствующий класс для создания экземпляра.
Мэтт Велке
5

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

Например, вы обычно запускаете свою деятельность через панель запуска, а затем «минимизируете» ее. Затем вы запускаете другое приложение (например, Tasker), которое запускает другой экземпляр вашей активности, например, для создания ярлыка, потому что ваше приложение поддерживает android.intent.action.CREATE_SHORTCUT. Если затем создать ярлык, и этот вызов действия создания ярлыка изменил данные объекта приложения, то действие, выполняющееся в фоновом режиме, начнет использовать этот измененный объект приложения, как только оно будет возвращено на передний план.

Даниэль Ф
источник
4

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

public class MyApplication extends Application {

    private static final String TAG = MyApplication.class.getSimpleName();

    private static MyApplication sInstance;

    @Contract(pure = true)
    @Nullable
    public static Context getAppContext() {
        return sInstance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate() called");
        sInstance = this;
    }
}

И синглтоны выглядят так:

public class DataManager {

    private static final String TAG = DataManager.class.getSimpleName();

    @Contract(pure = true)
    public static DataManager getInstance() {
        return InstanceHolder.INSTANCE;
    }

    private DataManager() {
        doStuffRequiringContext(MyApplication.getAppContext());
    }

    private static final class InstanceHolder {
        @SuppressLint("StaticFieldLeak")
        private static final DataManager INSTANCE = new DataManager();
    }
}

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

Совет: обновление синглтон-шаблона Android Studio экономит много времени.

Сэр кодесалот
источник
3

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

Typeface.createFromAsset()

из каждой операции, чтобы получить ссылки на мои шрифты из папки «Ресурсы» (это плохо, потому что это приведет к утечке памяти, поскольку вы сохраняете ссылку на ресурсы каждый раз, когда вызываете этот метод), я делаю это из onCreate()метода в моем классе Application :

private App appInstance;
Typeface quickSandRegular;
...
public void onCreate() {
    super.onCreate();

    appInstance = this;
    quicksandRegular = Typeface.createFromAsset(getApplicationContext().getAssets(),
                       "fonts/Quicksand-Regular.otf");
   ...
   }

Теперь у меня также есть метод, определенный следующим образом:

public static App getAppInstance() {
    return appInstance;
}

и это:

public Typeface getQuickSandRegular() {
    return quicksandRegular;
}

Итак, из моего приложения все, что мне нужно сделать, это:

App.getAppInstance().getQuickSandRegular()

Другое использование для класса Application для меня - это проверить, подключено ли устройство к Интернету, ПРЕЖДЕ ЧЕМ действия и службы, которые требуют фактического подключения, предпринимают необходимые действия.

Оджонугва Джуд Очалифу
источник
1
Хорошо сказано. Очень приятно сломаться.
Олуватоби Аденекан
3

Источник: https://github.com/codepath/android_guides/wiki/Understanding-the-Android-Application-Class

Во многих приложениях нет необходимости работать с классом приложения напрямую. Однако есть несколько приемлемых вариантов использования пользовательского класса приложения:

  • Специализированные задачи, которые необходимо выполнить перед созданием вашего первого действия
  • Глобальная инициализация, которая должна быть общей для всех компонентов (отчеты о сбоях, постоянство)
  • Статические методы для легкого доступа к статическим неизменяемым данным, таким как объект клиента общей сети

Вы никогда не должны хранить изменяемые данные экземпляра внутри объекта Application, потому что, если вы предполагаете, что ваши данные останутся там, ваше приложение неизбежно завершится сбоем в какой-то момент с исключением NullPointerException. Объект приложения не гарантированно останется в памяти навсегда, он будет уничтожен. Вопреки распространенному мнению, приложение не будет перезапущено с нуля. Android создаст новый объект Application и запустит действие, в котором он находился ранее, чтобы создать иллюзию, что приложение никогда не было убито.

Periworks
источник
1

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

Таран Махал
источник
1

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

http://www.intridea.com/blog/2011/5/24/how-to-use-application-object-of-android

Вишал Джайн
источник
это не поток, так что «для любой операции, которую вы хотите в течение всего периода работы приложения». это не правда.
Ласси Киннунен
1

Чтобы добавить к другим ответам, которые утверждают, что вы можете хранить переменные в области приложения, для любых длительных потоков или других объектов, которым требуется привязка к вашему приложению, если вы НЕ используете действие (приложение не является действием). например, невозможность запросить привязанную услугу .. тогда предпочтительнее привязка к экземпляру приложения. Единственным очевидным предупреждением при таком подходе является то, что объекты живут до тех пор, пока приложение живо, поэтому требуется более явный контроль над памятью, иначе вы столкнетесь с проблемами, связанными с памятью, такими как утечки.

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

2018-10-19 11:31:55.246 8643-8643/: application created
2018-10-19 11:31:55.630 8643-8643/: activity created
Дэвид Маки
источник