0

my RoomDB always jumps into the if(INSTANCE==null) block even though the db was created on the first run.
This is my ShishacounterRoomDatabase.class:

package com.example.shishacounter;

import android.content.Context;
import android.os.AsyncTask;

import androidx.room.Database;
import androidx.room.RoomDatabase;
import androidx.room.Room;

import com.example.shishacounter.dao.CoalDao;
import com.example.shishacounter.dao.SmokedDao;
import com.example.shishacounter.dao.TobaccoDao;
import com.example.shishacounter.models.Coal;
import com.example.shishacounter.models.Smoked;
import com.example.shishacounter.models.Tobacco;


@Database(entities = {Tobacco.class, Coal.class, Smoked.class}, version=2, exportSchema = false)
public abstract class ShishaCounterRoomDatabase extends RoomDatabase {

    public abstract TobaccoDao tobaccoDao();
    int tobaccoLength;

    public abstract CoalDao coalDao();
    int coalLength;

    public abstract SmokedDao smokedDao();

    private static ShishaCounterRoomDatabase INSTANCE;

    public static  synchronized ShishaCounterRoomDatabase getInstance(Context context){
        if(INSTANCE == null){
            INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                    ShishaCounterRoomDatabase.class,
                    "db")
                    .build();
            INSTANCE.populateInitialData();
        }
        return INSTANCE;
    }

    private void populateInitialData(){
        new GetTobaccoLengthTask().execute();
        new GetCoalLengthTask().execute();

        if(tobaccoLength == 0){
            new InsertTobaccoTask().execute();
        }
        if(coalLength == 0){
            new InsertCoalTask().execute();
        }
    }

    private class GetTobaccoLengthTask extends AsyncTask<Void, Void, Integer> {

        @Override
        protected Integer doInBackground(Void... voids) {
            return INSTANCE.tobaccoDao().count();
        }

        @Override
        protected void onPostExecute(Integer integer) {
            super.onPostExecute(integer);
            tobaccoLength = integer;
        }
    }

    private class GetCoalLengthTask extends AsyncTask<Void, Void, Integer>{

        @Override
        protected Integer doInBackground(Void... voids) {
            return INSTANCE.coalDao().count();
        }

        @Override
        protected void onPostExecute(Integer integer) {
            super.onPostExecute(integer);
            coalLength = integer;
        }
    }

    private class InsertTobaccoTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... voids) {
            for(int i=0; i<Tobacco.populateData().length; i++) {
                tobaccoDao().insert(Tobacco.populateData()[i]);
            }
            return null;
        }
    }

    private class InsertCoalTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... voids) {
            for(int i=0; i<Coal.populateData().length; i++) {
                coalDao().insert(Coal.populateData()[i]);
            }
            return null;
        }
    }
}

If I run the App a second time the Logcat shows me these Errors:

2019-11-26 23:43:04.150 23774-23774/? E/e.shishacounte: Unknown bits set in runtime_flags: 0x8000
2019-11-26 23:43:04.240 23774-23805/? E/Perf: Fail to get file list com.example.shishacounter
2019-11-26 23:43:04.240 23774-23805/? E/Perf: getFolderSize() : Exception_1 = java.lang.NullPointerException: Attempt to get length of null array
2019-11-26 23:43:04.240 23774-23805/? E/Perf: Fail to get file list com.example.shishacounter
2019-11-26 23:43:04.240 23774-23805/? E/Perf: getFolderSize() : Exception_1 = java.lang.NullPointerException: Attempt to get length of null array
2019-11-26 23:43:04.388 23774-23816/? E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #1
    Process: com.example.shishacounter, PID: 23774
    java.lang.RuntimeException: An error occurred while executing doInBackground()
        at android.os.AsyncTask$4.done(AsyncTask.java:399)
        at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
        at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
        at java.util.concurrent.FutureTask.run(FutureTask.java:271)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
     Caused by: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: tobacco.id (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY)
        at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
        at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:879)
        at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:790)
        at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:88)
        at androidx.sqlite.db.framework.FrameworkSQLiteStatement.executeInsert(FrameworkSQLiteStatement.java:51)
        at androidx.room.EntityInsertionAdapter.insert(EntityInsertionAdapter.java:80)
        at com.example.shishacounter.dao.TobaccoDao_Impl.insert(TobaccoDao_Impl.java:72)
        at com.example.shishacounter.ShishaCounterRoomDatabase$InsertTobaccoTask.doInBackground(ShishaCounterRoomDatabase.java:89)
        at com.example.shishacounter.ShishaCounterRoomDatabase$InsertTobaccoTask.doInBackground(ShishaCounterRoomDatabase.java:84)
        at android.os.AsyncTask$3.call(AsyncTask.java:378)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:919) 

So the Database is clearly filled, but the App still runs the if(INSTANCE == null){...} block. But I don't know why.

Enes2802
  • 1
  • 2
  • `SQLiteConstraintException: UNIQUE constraint failed: tobacco.id`means: don't insert the same ID twice. And this question does not feature any `if(INSTANCE == null)` "block". Most likely those tasks run in a different sequence as you imagine them to run ...since running asynchronous without ever calling back; don't abuse `AsyncTask` alike that... one single import `AsyncTask` rather would work without calling back, even if it should call back when complete. – Martin Zeitler Nov 27 '19 at 11:32
  • Also see [Packing the Room: Pre-populate your database with this one method](https://medium.com/androiddevelopers/packing-the-room-pre-populate-your-database-with-this-one-method-333ae190e680). – Martin Zeitler Nov 27 '19 at 11:56

1 Answers1

0

Ofcourse INSTANCE will be null every time when you run your app. Singletone create single instance of the object but not a permanent immortal object https://www.journaldev.com/1827/java-design-patterns-example-tutorial#singleton-pattern. databaseBuilder doesn't mean that your database created from scratch. Your error said that you have problem with tobacco.id. I don't wanna copy paste possible answers. Here is variants of solutions https://stackoverflow.com/a/34980212/5422725