如何在不抛出异常的情况下在 IntentService 中查询房间数据库
How To Query Room Database Within An IntentService Without Throwing Exception
我正在查询 未被观察/非实时 数据,来自 IntentService 在 [=22] 中启动的数据=]PreferenceFragment。但是一秒钟我的应用程序崩溃并显示日志:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
at android.arch.persistence.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:204)
at android.arch.persistence.room.RoomDatabase.query(RoomDatabase.java:232)
at vault.dao.xxxDao_Impl.getAllNonLivePojoItems(xxxDao_Impl.java:231)
我想知道为什么我的程序会抛出这个异常。根据
我的数据库查询[s] 在 IntentService 中,该 IntentService 在其自己的线程中运行,所以我应该处于绿色状态。这是我的代码:
Inside IntentService
--------------------
// ERROR OCCURS HERE
List<POJO> pojoList = localRepo.getAllNonLivePojoItems(); // <= ERROR POINTS HERE
if (pojoList != null && pojoList.size() > 0) {
for (Pojo pojo : pojoList ){
// Do Long Running Task Here ....
}
我还实例化了正在使用的对象,并在 OnHandleIntent 中从 IntentService 中的那些对象调用上述方法,如下所示:
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
LocalRepo localRepo = new LocalRepo(this.getApplication());
PojoHelper pojoHelper = new PojoHelper(this, localRepo);
if (LOGOUT.equals(action) && type != null) {
Log.d(TAG, "onHandleIntent: LOGOUT");
pojoHelper.logoutPojo();
}
else if(DELETE.equals(action) && type != null){
Log.d(TAG, "onHandleIntent: DELETE_POJO");
pojoHelper.deletePojo(true);
}
}
}
我没有提到的一件事是该方法是在异步的响应回调方法中执行的
PojoWarehouse.processPojoItems(new AsyncPojoCallback() {
@Override
public void done(Exception e) {
if (e == null) {
// ERROR OCCURS HERE
List<POJO> pojoList = localRepo.getAllNonLivePojoItems(); // <= ERROR POINTS HERE
if (pojoList != null && pojoList.size() > 0) {
for (Pojo pojo : pojoList ){
// Do Long Running Task Here ....
}
} else
Log.d(TAG, "done: Error Logging Out: " + e.getLocalizedMessage());
}
});
我无法从技术层面解释为什么这解决了问题,但欢迎提出建议。
我假设您从在 UI 线程上运行的 AsyncTask
onPostExecute() 方法获得回调。禁止在 UI 线程内使用数据库或网络调用,因为它会阻塞 UI.
在新线程中访问数据库的地方执行代码。
示例:
Executors.newSingleThreadExecutor().execute(()->{
//TODO access Database
});
我正在查询 未被观察/非实时 数据,来自 IntentService 在 [=22] 中启动的数据=]PreferenceFragment。但是一秒钟我的应用程序崩溃并显示日志:
java.lang.IllegalStateException: Cannot access database on the main thread since it may potentially lock the UI for a long period of time.
at android.arch.persistence.room.RoomDatabase.assertNotMainThread(RoomDatabase.java:204)
at android.arch.persistence.room.RoomDatabase.query(RoomDatabase.java:232)
at vault.dao.xxxDao_Impl.getAllNonLivePojoItems(xxxDao_Impl.java:231)
我想知道为什么我的程序会抛出这个异常。根据
我的数据库查询[s] 在 IntentService 中,该 IntentService 在其自己的线程中运行,所以我应该处于绿色状态。这是我的代码:
Inside IntentService
--------------------
// ERROR OCCURS HERE
List<POJO> pojoList = localRepo.getAllNonLivePojoItems(); // <= ERROR POINTS HERE
if (pojoList != null && pojoList.size() > 0) {
for (Pojo pojo : pojoList ){
// Do Long Running Task Here ....
}
我还实例化了正在使用的对象,并在 OnHandleIntent 中从 IntentService 中的那些对象调用上述方法,如下所示:
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
LocalRepo localRepo = new LocalRepo(this.getApplication());
PojoHelper pojoHelper = new PojoHelper(this, localRepo);
if (LOGOUT.equals(action) && type != null) {
Log.d(TAG, "onHandleIntent: LOGOUT");
pojoHelper.logoutPojo();
}
else if(DELETE.equals(action) && type != null){
Log.d(TAG, "onHandleIntent: DELETE_POJO");
pojoHelper.deletePojo(true);
}
}
}
我没有提到的一件事是该方法是在异步的响应回调方法中执行的
PojoWarehouse.processPojoItems(new AsyncPojoCallback() {
@Override
public void done(Exception e) {
if (e == null) {
// ERROR OCCURS HERE
List<POJO> pojoList = localRepo.getAllNonLivePojoItems(); // <= ERROR POINTS HERE
if (pojoList != null && pojoList.size() > 0) {
for (Pojo pojo : pojoList ){
// Do Long Running Task Here ....
}
} else
Log.d(TAG, "done: Error Logging Out: " + e.getLocalizedMessage());
}
});
我无法从技术层面解释为什么这解决了问题,但欢迎提出建议。
我假设您从在 UI 线程上运行的 AsyncTask
onPostExecute() 方法获得回调。禁止在 UI 线程内使用数据库或网络调用,因为它会阻塞 UI.
在新线程中访问数据库的地方执行代码。
示例:
Executors.newSingleThreadExecutor().execute(()->{
//TODO access Database
});