NullPointerException в конструкторе сервиса
В моем проекте Android у меня есть Service
:
public class MyService extends Service{
//I defined a explicite contructor
public MyService(){
//NullPointerException here, why?
File dir = getDir("my_dir", Context.MODE_PRIVATE);
}
@Override
public void onCreate(){
super.onCreate();
...
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
...
}
}
Я обычно знаю, я не должен явно определять конструктор для Android Service
, Но в моем случае я хочу использовать конструктор для создания каталога во внутренней памяти.
Когда я пытаюсь это сделать, я получаю исключение NullPointerException, которое я не понимаю, почему? Может ли кто-нибудь объяснить мне причину, почему я получил NullPoineterException при вызове getDir(...)
в моем явном конструкторе?
4 ответа
getDir()
это метод в Context
,
Служба не настроена для использования в качестве Context
до тех пор onCreate()
,
По сути, структура устанавливает службы (и действия в этом отношении) следующим образом:
- Создать объект
- Настройте
Context
с соответствующими ресурсами для текущей конфигурации - Вызов
onCreate()
на объекте
Вы не можете делать ничего, что требует, чтобы объект был правильно настроен Context
на шаге 1, т.е. во время инициализации переменной-члена или конструктора.
Вы должны использовать функцию жизненного цикла сервиса onCreate(). Функция onCreate запускается только один раз в жизненном цикле сервиса и работает как конструктор. Если вы хотите, чтобы он обновлялся в любом месте, вы можете поместить его в onStartCommand(намерение намерения, флаги int, int startId).
Как сказал @laalto, сервис не настроен для использования в качестве контекста, пока onCreate().
Так что сделайте одну глобальную переменную Context.
Context ctx;
Также сделать конструктор для вашего класса MyService должно быть.
public MyService(Context mContext){
this.ctx = mContext;
File dir = ctx.getDir("my_dir", Context.MODE_PRIVATE);
}
Вероятно, в вашем сервисном конструкторе Context все еще пусто, а getDir использует Context для своей внутренней работы. Вы можете проверить это в следующих источниках:
243 @Override
244 public File getDir(String name, int mode) {
245 return mBase.getDir(name, mode);
246 }
так что если mBase равен нулю, вы получите NPE
mBase будет установлен в конструкторе:
56 public ContextWrapper(Context base) {
57 mBase = base;
58 }
Служба расширяет ContextWrapper, но конструктор службы вызывает непосредственно этот конструктор со значением NULL:
http://androidxref.com/4.4.2_r1/xref/frameworks/base/core/java/android/app/Service.java#294
294 public Service() {
295 super(null);
296 }
поэтому вы должны дождаться Service.onCreate() или (если можете) использовать некоторый глобально известный контекст, например, из вашего объекта приложения.