简体   繁体   中英

How To Query Room Database Within An IntentService Without Throwing Exception

I am querying POJO which is NOT being Observed / Non-Live data from an IntentService that was started in a PreferenceFragment . However a second my application crashes and log displays:

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)

I want to know why is my program throwing this exception. as per https://stackoverflow.com/a/23935791/8623507

my database query[s] are inside an IntentService that runs In its own thread so i should be in the green. here is my code:

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 ....
    }

Also I instantiate The Objects Being Used and call the above methods from those Objects Throughout the IntentService in OnHandleIntent like so:

@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);
        }
    }
}

I assume you get callback from AsyncTask onPostExecute() method which runs on UI thread. It is prohibited to use database or network calls inside UI thread because it can block UI.

Execute your code where you access database inside new thread.

Example:

        Executors.newSingleThreadExecutor().execute(()->{
             //TODO access Database
         });

One thing i failed to mention was that the method was being executed within an async's response callback method

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());
        }
    });

I cannot explain on a technical level why this fixed the issue, however suggestions are welcomed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM