getApplication () и охватывающие действия в пределах определенных приложений - PullRequest
1 голос
/ 16 октября 2011

Я потратил некоторое время, читая об этом, и до сих пор не нашел ответа.

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

Мы назовем мой общий класс приложения «MyApplication», а основное действие - «MyActivity». Я ожидал бы, что, как только приложение начинается с холодного запуска, оно сначала создает и инициализирует MyApplication (вызывая onCreate ()), а затем переходит к созданию и запуску моей активности (MyActivity) (которая была помечена намерением android.intent.action .ГЛАВНЫЙ). Журналы, кажется, подтверждают это.

Но ... если я попытаюсь установить следующую переменную для всей Деятельности, она будет установлена ​​в нуль: private final MyApplication THISAPP = (MyApplication) getApplication ();

Это необычно, потому что приложение определенно существует на данный момент. (Кроме того, я не могу отложить установку окончательной переменной, пока не будет вызван MyActivity.onCreate () - это запрещено («Окончательное поле ... не может быть назначено»)).

Обратите внимание, что это работает, если я не называю THISAPP "final" и назначаю его в onCreate (). Это, конечно, противоречит цели защиты переменной с помощью «final», и кажется, что это можно сделать.

Итак, почему getApplication () не генерирует ненулевое значение перед onCreate ()? Или это какой-то странный вопрос контекста? (Я обнаружил, что неопределенная ссылка на контекст недействительна, пока onCreate () не завершена, но будет ли это применяться к контексту родительского приложения, как видно из дочерней операции? I ожидал, что родитель уже установил этот набор на тот момент.)

Редактировать: чтобы подчеркнуть, я могу заставить это работать, если я не пытаюсь использовать final и если я не забываю поставить "." перед именем приложения в манифесте (ошибку я сделал и исправил задолго до этого я написал этот вопрос). Просто не ясно, почему getApplication () (или getApplicationContext () в этом отношении) нельзя использовать до onCreate () в дочернем Activity ... если только «это просто так».

Ответы [ 4 ]

3 голосов
/ 16 октября 2011

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

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

IОжидается, что, как только приложение начинается с холодного запуска, оно сначала создает и инициализирует MyApplication (вызывая onCreate ()), а затем переходит к созданию и запуску моей активности (MyActivity) (которая была помечена намерением android.intent.action.ГЛАВНЫЙ).Журналы, кажется, подтверждают это.

Правильно.

Но ... если я пытаюсь установить следующую переменную для всей Деятельности, она получает значение null:private final MyApplication THISAPP = (MyApplication) getApplication ();

Конечно.Объект действия еще не был инициализирован.Вы можете использовать подобные инициализаторы для констант или вещей, которые вы получаете от статических методов (например, Calendar.getInstance()) или других конструкторов (например, new ArrayList<Foo>()).Не вызывайте метод суперкласса, так как ожидайте, что он будет работать на этом этапе, поскольку цепочка конструктора еще не была вызвана для создаваемого объекта.Это просто Java, ничего особенного для Android.

2 голосов
/ 16 октября 2011

Переменные экземпляра создаются при создании объекта (в данном случае объекта Activity).Чтобы getApplication () мог создать допустимое значение, тогда объект Activity должен был бы предоставить достаточно контекста (маленький 'c') при создании экземпляра для этого.

Источник getApplication () в Activity.javaпросто так:

/** Return the application that owns this activity. */
public final Application getApplication() {
    return mApplication;
}

Вот где оно установлено:

final void attach(Context context, ActivityThread aThread, Instrumentation instr, IBinder token,
        Application application, Intent intent, ActivityInfo info, CharSequence title, 
        Activity parent, String id, Object lastNonConfigurationInstance,
        Configuration config) {
    // other code
    mApplication = application;
    // other code
}

Поскольку mApplication не устанавливается до тех пор, пока не будет вызвано присоединение, оно не будет доступно для getApplication ()на создание вашей деятельности.

2 голосов
/ 16 октября 2011

AFAIK, Вы не можете объявить пустую переменную final и инициализировать ее при создании. В Java это инициализируется во время объявления переменной или в конструкторе.

THISAPP не может быть инициализирован в Application объект во время объявления, потому что Application не существует во время компиляции. Поскольку onCreate не является конструктором, вы не можете объявить пустую переменную final и инициализировать ее в onCreate.

2 голосов
/ 16 октября 2011

Вы сделали это следующим образом?

Создан класс, реализующий приложение

public class MySuperApplication extends Application 
{ 
    public String SomeSetting; 
}

Определено, какой класс вашего приложения указан в манифесте (важно!)

<application android:name=".MySuperApplication" android:icon="@drawable/icon"

, а затем доступ к нему в вашей деятельности

app = (MySuperApplication) getApplication();
app.SomeSetting = "Test";

Это должно работать. Это в моем случае.

...