我最近通过JobService将JobScheduler添加到了我的应用中。我使用JobService在后台定期与数据库同步并更新本地Room DB实例。
但是,我看到任意崩溃并显示以下错误:
进程:com.application.name,PID:27229 java.lang.RuntimeException:无法实例化服务com.application.name.Services.SyncService: java.lang.NullPointerException:尝试调用虚拟方法 'android.content.Context 空对象上的android.content.Context.getApplicationContext()' 参考
完整的堆栈跟踪如下:
由java.lang.NullPointerException引起:尝试调用虚拟 方法'android.content.Context 空对象上的android.content.Context.getApplicationContext()' 参考 在com.application.name.Database.AppDatabase.getDatabase(AppDatabase.java:38) 在com.application.name.Services.SyncService。(SyncService.java:48) 在java.lang.Class.newInstance(Class.java) 在android.app.ActivityThread.handleCreateService(ActivityThread.java:3551) 在android.app.ActivityThread.-wrap4(未知来源) 在android.app.ActivityThread $ H.handleMessage(ActivityThread.java:1778) 在android.os.Handler.dispatchMessage(Handler.java:105) 在android.os.Looper.loop(Looper.java:164) 在android.app.ActivityThread.main(ActivityThread.java:6798) 在java.lang.reflect.Method.invoke(Method.java) 在com.android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote.java:240) 在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)
崩溃报告所引起的违规行是JobService构造函数中Room DB实例的实例化。
public SyncService() {
super();
database = AppDatabase.getDatabase(getApplication());
}
在Room DAO中,我有以下代码:
private static AppDatabase INSTANCE;
public static AppDatabase getDatabase(final Context context){
if(INSTANCE == null) {
synchronized (AppDatabase.class){
if(INSTANCE == null){
// Migration definitions go here
..
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, context.getResources().getString(R.string.database))
.allowMainThreadQueries()
.addMigrations(FROM_2_TO_3)
.build();
}
}
}
return INSTANCE;
}
所以我想我理解为什么会发生这种情况-当应用程序未运行时,应用程序上下文为Null,因此Room的数据库构建器在设置时会遇到问题。
我想知道的是,当应用程序不运行时,是否可以通过某种方式访问我的Room DB。从JobService将Context传递给初始化并编写辅助构造函数似乎很丑陋,可能会产生无法预测的条件,所以我想知道我还有哪些其他选择。
我可以做的一件事是将从JobService获取的数据写入SharedPreferences,然后在启动应用程序时将其同步到DB。还有其他办法吗?
答案 0 :(得分:1)
我想我错过了一个简单的事实-a Service IS a Context.
代替传递:
database = AppDatabase.getDatabase(getApplication());
我要做的就是这个:
database = AppDatabase.getDatabase(this);
到目前为止,我还没有发生任何重复的崩溃...。我仍然对其他答案持开放态度,因此,如果您认为我可以以更好的方式做到这一点,请采纳您的观点。
答案 1 :(得分:0)
applicationContext
应在调用 onCrate()
方法后调用。因此,您需要在 onCreate()
方法中运行您的代码。