Complete App From Scratch: Kotlin Part 3 — Deep Dive into the Database

Yash Prakash
This Code
Published in
5 min readSep 10, 2020

Welcome to the Part 3 of the Remember app series!

Now that we have the complete design of the app built, in this part, I think we’re ready to take the leap and jump into some code. :)

Photo on Unsplash

The most important part of our app will be the database — the Room database which we’ll use to store the words (names + meanings). As I said in Part Two of the series, we’ll be storing the pronunciation audio that the user records for any word directly on the phone’s local internal storage, but anyway, we’ll need some kind of reference to the stored audio in order to access it later.

That reference will also be defined in our Word model class.

If you are new to using the Room library, I have a small introductory repository published in my GitHub which helps you easily understand the basics and get you started with working with it in your own app. Read more about it and use it here. :)

Let’s have a look at our Word database model class. We’ll call this simply — Word.kt.

word entity class

As you can see, we’ll be storing three main properties we’ll associate with any word:

  1. name: of string type which will be compulsory. (we’ll show an error when the user tries to save a word without entering the name itself.)
  2. meaning: of string type also but it can be null.
  3. audioPath: this is the variable that will store the full path of the pronunciation file from the internal storage. This can also be null as providing a pronunciation will be optional for storing a new word in the database.

Note: You’ll need the imports for Room database in your app level Gradle file.

//Room
def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
kapt "androidx.room:room-compiler:$room_version
// optional - Kotlin Extensions and Coroutines support for Room
implementation "androidx.room:room-ktx:$room_version"
// Select the version number latest at the point you read this
// article.

Next comes our database access object or DAO.

Room persistence flow

I’ll briefly define what DAOs are and why they are necessary in our app. In short, this interface class will contain the methods we’ll be using for accessing our database.

Specifically, here’s how the android developers documentation describes the use of DAOs:

The app uses the Room database to get the data access objects, or DAOs, associated with that database. The app then uses each DAO to get entities from the database and save any changes to those entities back to the database.

Let’s now look at the methods we’ll be using in our DAO to understand it more clearly.

We can define the interface simply like this:

@Dao
interface WordDao {
// the methods we need to access the db will then be defined in the
// following gist:
dao class

These entail the basic functionalities of Remember: Inserting a word, updating and deleting a word and getting a list of words as a Paged List.

For our list and grid views showing the words from the database, we’ll be using the Android Paging Library. We’ll worry a bit more about this in a later part of the series when we actually get to displaying the words in our Recyclerview lists — first we will need to get the insert functionality working.

The Database Class

We need to initialise our database and for that we need to make sure we use a singleton object as our main access point for our database. The code snippet below does exactly that.

the db class

Our repository class will then be needed to defined. This class will be our way of implementing the DAO methods for our CRUD operations.

WordRepository class will contain the access to the WordDatabase object which we will get as a constructor argument from any activity or fragment we’ll define later on.

We’ll define it like this:

class WordRepository(private val database: WordDatabase) {...}

Accessing the DAO methods is simple enough as well.

fun getAllWordsRoomPaged() : DataSource.Factory<Int, Word>
= database.wordDao().getAllWordsPaged()

The above method gets all our words from the database as a paged list.

A paged list is used to load and display small chunks of data at a time, and on demand. It helps to reduce the use of network bandwidth — if we’re fetching data from a remote database like an API call, or to reduce the load and wait time along with large memory overheads if we’re loading data from a local database, like we are doing it in this app.

It is a part of the Android Jetpack and can be defined in the app level Gradle like this:

// Paging - use the latest version from the developer page or this
// one if you want to be consistent with this tutorial.
def paging_version = "2.1.2"
implementation "androidx.paging:paging-runtime:$paging_version"

Let’s first define a few more functions for our repository class and then we’ll see a bit more about the paging library components.

For insertion and deletion:

@Query("Delete from word_table where name like :name")
fun deleteWord(name: String)

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun insertWord(word: Word)

And for updating a word:

@Query("Update word_table set name = :name, meaning = :meaning, audioPath = :audiopath where name like :originalName")
fun updateWord(originalName: String, name: String, meaning:String?, audiopath: String?)

Loading words in alphabetical order.

An alternate option for loading all words — to make the list of words appear alphabetically in our Recyclerview later, we can use another function to order our words by name, like below:

@Query("Select * from word_table order by name")
fun getAllWordsPagedAlphabetically() : DataSource.Factory<Int, Word>

If we need to define more methods, we’ll do so as we move along with this series. But for now, I think we’re good to go and start making the activity and fragment classes and make our XML UI as well, which we can start doing in the next article.

Until then, I have the complete code for the app ready for you in my GitHub repo. The app is fully functional and every feature I’ll be covering in this series of articles has been implemented in the code. Here’s the link, and I hope you can follow along better with the code at your fingertips along with these articles.

Please be sure to leave a few claps for this story if you find it helpful, and I’ll be seeing you in the next one. ❤

Do you want to get one free, clean email from me every week or two weeks containing the best of my curated articles and tutorials that I publish? Join my Codecast!

Connect with me on Twitter and LinkedIn!

--

--

Yash Prakash
This Code

Software engineer → Solopreneur ⦿ Scaling my own 1-person business model ⦿ Writing for busy founders and business owners.