3

How can I easily get the count of the database size so I can then do the appropriate actions based on whether the DB is empty or not?

I have an App DB, View Model, Repository, Dao, and all the other pieces, and my objects insert... But I cannot call in onCreate() the size of the list in the DB. When I ever try to get mAppDatabase.vehicleDao().getAll().getValue().size(), or mVehicleViewModel.getAll().getValue().size(), I get null pointer exceptions.

However I know my objects are inserting because when I run an observable, I can log their information... but I cannot get the count on the main thread/ in onCreate. Help! Example code below:

protected void onCreate(Bundle savedInstanceState) {
...
mAppDatabase = AppDatabase.getInstance(MyActivity.this);
Log.d("LISTSIZEAPP", String.valueOf(mAppDatabase.myDao().getAll().getValue().size()));
ObserveItems();

OR

protected void onCreate(Bundle savedInstanceState) {
...
mViewModel = ViewModelProviders.of(this).get(MyViewModel.class);
Log.d("LISTSIZEVM",  String.valueOf(mViewModel.getAll().getValue().size()));
ObserveItems();

^Null pointer exception for both (Attempt to invoke interface method 'java.lang.Object[] java.util.List.toArray()' on a null object reference)...

however:

private void ObserveItems() {
    mViewModel.getAll().observe(this, new Observer<List<Foo>>() {
        @Override
        public void onChanged(@Nullable final List<Foo> foos) {
            mFoos= foos;
            for (Vehicle v: mFoos) {
                Log.d("ROOM INFO - FOOS", v.getFooTitle());
            }
        }
    });
}

I can log all the info I want. So the items are CLEARLY inserted. What gives? What am I missing? Thank you.

Levi Moreira
  • 11,917
  • 4
  • 32
  • 46
darkknightsds
  • 530
  • 8
  • 16
  • "I get null pointer exceptions" -- please provide full Java stack traces for the `NullPointerExceptions`, along with the code of yours that is referenced in those traces. As it stands, we do not know what either `getAll()` is or what `getValue()` is, let alone which of those calls (or something else) is what is throwing the `NullPointerException`. – CommonsWare May 17 '18 at 19:43

1 Answers1

7

This is accessing data synchronously from the LiveData:

Log.d("LISTSIZEVM",  String.valueOf(mViewModel.getAll().getValue().size()));

But this data might no have arrived yet.

Try adding this query to your Dao, see google samples:

@Query("SELECT COUNT(column) FROM table")
int getDataCount();

As pointed out by @CommonsWare this cannot be called from the main UI thread because it's a database opearation that will block the UI thread and will throw an error. You can either call this off the main thread, or return a LiveData<Integer> and observe the value, like you did with the list of data.

@Query("SELECT COUNT(column) FROM table")
LiveData<Integer> getDataCount();
Levi Moreira
  • 11,917
  • 4
  • 32
  • 46
  • 2
    Note that `getDataCount()` will crash if called on the main application thread, as Room blocks synchronous I/O when called on the main application thread. – CommonsWare May 17 '18 at 19:51
  • 1
    Thank you for the clarifications. I just ran into that issue. I will try calling a function that gets the count. – darkknightsds May 17 '18 at 19:55
  • Thanks for checking, Levi. I was able to get the count statement working using mAppDatabase.myDao().getCount() > 0, but only by adding .allowMainThreadQueries() on the AppDatabase. However now I am having trouble accessing any other info from the database. For example if I do mAppDatabase.myDao().findById(id).getValue().property I am still getting a null pointer exception. – darkknightsds May 21 '18 at 17:20
  • the problem is that you're trying to access your database in a syncronous way but database reads should be done in a async way, like you've noticed when you've used the observe method. – Levi Moreira May 21 '18 at 17:29
  • 1
    I moved my UI items to the observe function and am having better success now. Are there any resources you can point me to to help me better understand sync vs. async? – darkknightsds May 21 '18 at 18:02
  • I like to use some questions from SO because they give you insight and sometimes actual examples of these things: https://stackoverflow.com/questions/748175/asynchronous-vs-synchronous-execution-what-does-it-really-mean https://stackoverflow.com/questions/36213948/what-is-the-difference-between-asynchronous-calls-and-callbacks – Levi Moreira May 21 '18 at 18:12
  • Thank you so much for sharing. I will review those – darkknightsds May 21 '18 at 19:34
  • Thanks, definitely helps with the basics. I will definitely be doing a lot more research on this topic and how it relates to Room, specifically. Question - have you ever worked with Room callbacks? I have seen them used mainly for pre-populating the DB but are there other practical uses? – darkknightsds May 22 '18 at 15:56