Skip to main content

Prepopulate Room with data.


There are times, when we just need the data when the app starts, and all the functionality is just a matter of work. Or we just need the app to be independent from the network and we have the data. A simple dog-race database or cat-race database doesn't actually need online interaction at all (if there are not too many data of course). So, Room comes with a nice solution about this. The docs are pretty clear and short when it comes to this topic.
We just write:

Room.databaseBuilder(appContext, AppDatabase.class, "Sample.db")
    .createFromAsset("database/myapp.db")
    .build()
And our data are ready to be instantiated when the app starts. One more thing to note is that its extremely fast to do it this way. However, here are some problems that the docs don't even bother to mention (which I think are important for some).

1 - A .db file, is not a .sql file.

The file we are supposed to hold in assets folder which contains a query like: CREATE TABLE IF NOT EXISTS has nothing to do with the file in the code above, that we are supposed to import. We need to create a database like this. I actually used SqliteBrowser, to execute the query, but there should be other ways too.

2 - Null values and naming

Our data model needs to be precisely as the data we are supposed to prepopulate. For example if we have a [name] TEXT NULL we should make sure that the representation of it must meet the same conditions, including nullability and naming (this also includes table names):
@ColumnInfo(name = "name")
val name: String? = "",
Otherwise, we would feel some serious trouble. If we have the correct set up, let Room to connect the rest (the Sqlite table and it's Kotlin/Java object representation).

3- Must have incremental processor enabled:

Don't forget to have the correct setup in build.gradle (or in my case build.gradle.kts), because this feature is only available after Room 2.2.0:
  javaCompileOptions {
            annotationProcessorOptions {
                arguments = mapOf(
                    "room.schemaLocation" to "$projectDir/schemas",
                    "room.incremental" to "true",
                    "room.expandProjection" to "true"
                )
            }
        }

How to know if we are doing it correctly?

There are two cases to spot here:

1 - We have the incorrect file

In this case Room would automatically throw a RuntimeException yelling: "Cannot copy database file".

2 - The file is correct but the table in SQL has nothing to do with our model representation

In this case Room would throw a SqliteException with some error like: "Database file is corrupt". Trust me whatever you google on this case, cannot help 😅.

Note: This article is just about importing a .db file from assets folder. You can also import a db file from the device after download. Please check the docs for more.

A wish I made.

Well, I would like to see an option from Room to import a JSON as a file. Should be cool to have it as a feature.

Conclusion:

I hope I helped anyone who is willing to write an app with totally offline data. It's pretty good solution, when we don't have too much.

Stavro Xhardha

Popular posts from this blog

Modularizing your Android app, breaking the monolith (Part 1)

Inspired by a Martin Fowlers post about Micro Frontends, I decided to break my monolithic app into a modular app. I tried to read a little more about breaking monolithic apps in Android, and as far as I got, I felt confident to share my experience with you. This will be some series of blog posts where we actually try to break a simple app into a modularized Android app.

Note: You should know that I am no expert in this, so if there are false statements or mistakes please feel free to criticize, for the sake of a better development. 

What do you benefit from this approach:
Well, people are moving pretty fast nowadays and delivery is required faster and faster. So, in order to achieve this, modularising Android apps is really necessary.You can share features across different apps. Independent teams and less problems per each.Conditional features update.Quicker debugging and fixing.A feature delay doesn't delay the whole app. As per writing tests, there is not too much difference about…

From Gson to Moshi, what I learned

There is no doubt that people are getting away from GSON and I agree with those reasons too. The only advantage GSON has over other parsing libraries is that it takes a really short amount of time to set up. Furthermore, the most important thing is that Moshi is embracing Kotlin support.

First let's implement the dependency:
implementation("com.squareup.moshi:moshi:1.8.0") It's not a struggle to migrate to Moshi. It's really Gson look-a-like. The only thing to do is annotate the object with @field:Json instead of @SerializedName (which is Gsons way for JS representation):

data class User( //GSON way @SerializedName("name") val name: String, @SerializedName("user_name") val userName: String, @SerializedName("last_name") val lastName: String, @SerializedName("email") val email: String ) data class User( //Moshi way @field:Json(name = "name") val name: String, @field:Json(name = "user_name…

Modularizing your Android app, breaking the monolith (Part 2)

This is part 2 of a series of articles about modularizing Android app. If you haven't yet read the first article, you may find it here.

On our first article we just moved some classes outside the application and applied as an independent module. But what if we have dependencies pulled from the application level? This could be a small challenge. First of all, we want to clarify on how are we going to modularize the app. And depending on the previous article, I chose the by feature version of modularization. First of all, let's show some dependencies that are going to be needed in the whole app.

Note: I'm using Dagger for handling dependencies but manual DI or any dependency tool should be fine to understand this part.

So, this is my dependency schema:


Well, it's not that bad, but this isn't what we want to transform to when trying to modularize the app. If you think about it, modules that don't need a dependency, can get it quite easily. For example: A FeatureXVi…