Search code examples
androidkotlinandroid-room

Android Room parse before inserting


Imagine receiving from an endpoint an object like this

data class Foo(
    val name: String,
    val start: String,
    val end: String
)

where the properties start and end are string in the format of "00:00:00" to represent the hours, minutes and second from midnight.

I need to save this object in a Room table but with start and end parsed as Int instead of string.

The solution I resorted is this:

data class Foo(
    val name: String,
    val start: String,
    val end: String,
    var startInSeconds: Int = 0,
    var endInSeconds: Int = 0
) {
    init {
        startInSeconds = this.convertTimeInSeconds(this.start)
        endInSeconds = this.convertTimeInSeconds(this.end)
    }

    private fun convertTimeInSeconds(time: String): Int {
        val tokens = time.split(":".toRegex())
        val hours = Integer.parseInt(tokens[0])
        val minutes = Integer.parseInt(tokens[1])
        val seconds = Integer.parseInt(tokens[2])
        return 3600 * hours + 60 * minutes + seconds
    }
}

But I'd like to avoid to parse the start and end every time.

There is a way to parse before inserting?


Solution

  • you can try my solution if you want ,

    1. first, instead of using the same object Foo to store your data , it is better to create another data class as Entity to encapsulate the data.
    data class Bar(
        val name: String,
        val start: String,
        val end: String,
        val startInSeconds: Int, // <<-- using val to make data read only
        val endInSeconds: Int // <<-- using val to make data read only
    ) 
    
    1. you might need to create a thousand of object depend on your data size, so using companion object seems to be a good idea to parse the data to avoid unnecessary memory allocation .
    data class Bar(
        val name: String,
        val start: String,
        val end: String,
        val startInSeconds: Int,
        val endInSeconds: Int
    ) {
    
      companion object {
            // overloading the invoke function
            operator fun invoke(foo:Foo) : Bar {
                return Bar(
                   name = foo.name,
                   start = foo.start,
                   end = foo.end,
                   startInSeconds = convertTimeInSeconds(foo.start),
                   endInSeconds = convertTimeInSeconds(foo.end)
                )
            }
    
            private fun convertTimeInSeconds(time: String): Int {
               val tokens = time.split(":".toRegex())
               val hours = Integer.parseInt(tokens[0])
               val minutes = Integer.parseInt(tokens[1])
               val seconds = Integer.parseInt(tokens[2])
               return 3600 * hours + 60 * minutes + seconds
           }
        } 
    
    }
    
    //how to use
    fun insertToDatabase(foo:Foo){
       val parsedData = Bar(foo)
       dao.insert(parsedData)
    }