Навіщо розширювати клас додатків для Android?


168

Розширений Applicationклас може оголошувати глобальні змінні. Чи є інші причини?


Це лише ідея вгорі моєї голови, але ви повинні мати можливість змінити режим onCreate і показати екран одноразового запуску, а не MainActivity, тобто вступний екран, коли користувач відкриває додаток.
btse

Відповіді:


29

Я, очевидно, не можу придумати реального сценарію, коли розширення програми є кращим перед іншим підходом або необхідне для досягнення чогось. Якщо у вас є дорогий, часто використовуваний об'єкт, ви можете ініціалізувати його в IntentService, коли виявите, що об'єкт зараз не присутній. Сама програма працює на потоці інтерфейсу користувача, тоді як IntentService працює на власному потоці.

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


39
Існує багато застосувань розширеного класу додатків. Одним з дуже корисних є ловлі всіх невловимих винятків у вашому додатку. Так що це може бути дуже зручно
png

3
Як ти це робиш ?
serj

8
+1 для "prefer to pass data from Activity to Activity with explicit Intents, or use SharedPreferences". Ми завжди повинні максимально ліквідувати глобальну державу і використовувати стандартні інструменти Android для управління глобальним станом замість статичних vars /
синглонів

9
чому? підготуватися до андроїда в якийсь момент, запускаючи їх у різних процесах або будь-який компонент, який може бути повторно використаний будь-яким додатком, хоча це навмисно обмежено? просто передача об'єктів даних замість їх серіалізації економить процесор та пам'ять. Посилка для парцеляції для передачі всередині цього ж пристрою не є ідеальною. Я дійсно не бачу сенсу в застосуванні таких служб (просто виконайте інший потік з новим). насправді багато чого, що бентежить кодери, походить від того, що майже всі додані 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 мало пам'яті.

Чому у розділі "Вимога" чому б не використовувати SharedPreferences?

У першому прикладі, наприклад, для збереження особистих відомостей, можна використовувати SharedPreferences. Але приклади, які ви подали в останній частині, очистили мої сумніви. Дякую!
Саураб Сінгх,

63

Клас програми - це об'єкт, що має повний життєвий цикл вашої програми. Це ваш найвищий рівень як додаток. Приклад можливих звичаїв:

  • Ви можете додати те, що потрібно під час запуску програми, замінивши onCreate у класі програми.

  • зберігати глобальні змінні, що переходять від активності до активності. Як і Асинтактаск.

    тощо


4
Використання програми як демпінгу для глобальних змінних додатків - це великий запах коду. Для цього слід використовувати свої власні, більш конкретні класи як одиночні кнопки або зі статичними змінними.
Остін

5
@Austin чому це запах?
Relm

1
Так, чому пахне? Як було сказано раніше, клас 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;
    }
}

Для отримання додаткової інформації натисніть Клас програми


2
люб'язно поясніть мені це, чому нам потрібно явно зробити singleton об'єктом класу Application, наскільки я знаю, це сам синглтон. Чи можемо ми зробити кілька об’єктів додатків, якщо можемо, то як? і які наслідки? Ласкаво поясніть.
Syed Raza Mehdi

Ні, напевно, лише один клас застосування. developer.android.com/guide/topics/manifest/…
IntelliJ Amiya

то чому нам потрібно явно підтримувати однотонний об'єкт? Чи не підтримує ОС це для нас? Насправді я зіткнувся з кодом, у якому є об’єкт програми, зроблений у класі активності, і він не згадується в маніфесті. Я думаю, що це неправильно, також мені цікаво, чому ми робимо статичний одиночний об’єкт. Як ви думаєте, найкращий підхід. Дякуємо за відповідь.
Syed Raza Mehdi

1
дякую, я знайшов свою відповідь тут за цим посиланням developer.android.com/reference/android/app/Application.html
Syed Raza Mehdi

Де в цьому об’єкт * одиночний *
доктор aNdRO

8

Клас програми - синглтон, до якого ви можете отримати доступ з будь-якої діяльності або з будь-якого іншого місця, у якого є об'єкт контексту.

Ви також отримаєте трохи життєвого циклу.

Ви можете використати метод onCreate програми для створення екземплярів дорогих, але часто використовуваних об'єктів, таких як помічник аналітики. Потім ви можете отримати доступ до цих об'єктів і використовувати їх скрізь.


6
"Ви також отримаєте трохи життєвого циклу". ви можете переробити це.
wtsang02

2
Я маю на увазі, що ви отримуєте кілька дзвінків із життєвого циклу, але не стільки, скільки з діяльністю чи фрагментом. Наприклад, для класу Application немає OnDestroy ().
Джон F Hancock

Чи створений цей клас автоматично?
Костянтин Конопко

Так. Поки ви правильно вказали його в AndroidManifest.xml.
Джон F Hancock

Ні, він не створюється автоматично. Вам потрібно створити його, а потім оголосити його у вашому файлі маніфесту
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 (), і набрати його до класу додатків. Наскільки я зрозумів це поняття, що клас програми створюється самою ОС, і він повинен мати лише один екземпляр, який підтримується ОС. Ласкаво поясніть, дякую.
Syed Raza Mehdi

Ви маєте рацію. Виклик 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

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

Typeface.createFromAsset()

від кожної діяльності, щоб отримати посилання на мої шрифти з папки "Активи" (це погано, оскільки це призведе до витоку пам'яті, оскільки ви зберігаєте посилання на активи щоразу, коли ви викликаєте цей метод), я це роблю з onCreate()методу в моєму класі додатків :

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
Добре сказано. Дуже приємно ламатися.
Oluwatobi Adenekan

3

Джерело: https://github.com/codepath/android_guides/wiki/Understanding-the-Android-Application-Class

У багатьох додатках не потрібно безпосередньо працювати з класом додатків. Однак існує кілька прийнятних цілей користувацького класу додатків:

  • Спеціалізовані завдання, які потрібно виконати до створення вашої першої діяльності
  • Глобальна ініціалізація, яку потрібно розділити на всі компоненти (звітність про збої, наполегливість)
  • Статичні методи для легкого доступу до статичних незмінних даних, таких як об'єкт загального клієнтського мережі

Ніколи не слід зберігати змінні дані екземпляра всередині об’єкта Application, тому що якщо ви припускаєте, що ваші дані залишаться там, ваша програма неминуче в якийсь момент вийде з ладу з NullPointerException. Об'єкт програми не гарантовано залишиться в пам'яті назавжди, він загине. Всупереч поширеній думці, додаток не буде перезапущено з нуля. Android створить новий об’єкт програми та розпочне діяльність, у якій користувач раніше був, ілюзію, що додаток ніколи не вбито.


1

Ви можете отримати доступ до змінних до будь-якого класу, не створюючи об'єктів, якщо його розширено програмою Application. Їх можна назвати по всьому світу, і їх стан зберігається, поки заява не буде знищена.


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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.