Sometimes we need an application to be prefilled with some data on its first launch. Usually, we would make a REST query and receive the data from backend, but our application is standalone so that the only data source we have is our apk file.
In this article, I will describe a recipe how to prepopulate Room database with a small data set and how to do it in a few simple steps. Another profit from the approach below is that you can populate data from system resources and you can benefit from localization of the resources.
Let's suppose that we need to develop an application with a set of the largest cities available after first application start. It would be nice for a user to see a list of cities related to user's location.
Let's put the largest cities in a simple Room Entity like this:
Here is the list of three simple steps we need to implement:
- Create a Singleton for RoomDatabase instance
- Add a callback on creating data base
- Populate database
As you know, we should have only one instance of RoomDatabase within application to have it working correctly. So that we create a Singletone for RoomDatabase instance.
This is a regular thread safe, lazy Singletone. The idea is pretty straightforward – instantiate RoomDb in case it is NOT instantiated yet. Also we synchronize the method so that calls from different threads wait until the RoomDb instantiation is finished.
Next, we add a callback while creating our database. Here is the code:
In the above code, we implement Callback and override its onCreate method with parameter
SupportSQLiteDatabase. However, we want to use the power of Room ORM rather than inflating database with SQL queries. Therefore, we need to obtain an instance of RoomDb within the onCreate callback as soon as instantiation of RoomDb is finished. To achieve this, we call getInstance() in a dedicated Thread and this is the place where we get use of Singleton thread safety feature.
Now, with RoomDb instance and Android Context we call method prepopulateDb:
In this method, we merely get instance of CityDao and insert there a set of largest cities from string resources. For each user location we can have a dedicated set of cities, so that to change pre-populated data you only need to edit string resources.
As you can see this approach is very straightforward for implementation. However, if you need to prefill database with a huge dataset you should consider another approach and copy database file from asset to your database application folder.
Of course, you might want to use Dagger for Singleton, in this case you need to adopt the Singleton for using in a Dagger module.
You can find a simple related project here.
Feel free to contact us with some comments on this article.