• 3
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

I was wondering if anyone found a way to use kotlins extension functions as TypeConverter methods when using Room database. The code looks super clean, but I've not been able to find a way to add the converter to RoomDatabases array of converters:

enum class Status(val code: Int) {
    ACTIVE(0), INACTIVE(1), COMPLETED(2)
}

@TypeConverter
fun Status.toInt() : Int = this.code // This could be shorter I know

@TypeConverter
fun Int.toStatus() : Status = when(this) { // This could also be shorter
    Status.ACTIVE.code -> Status.ACTIVE
    Status.INACTIVE.code -> Status.INACTIVE
    Status.COMPLETED.code -> Status.COMPLETED
    else -> {
        Timber.e("Could not recognize Status")
        throw IllegalArgumentException("Could not recognize Status")
    }
}

Even the tests look super elegant:

class SampleConverterTest {

    @Test
    fun fromIntToActiveStatus() {
        assertThat(Status.ACTIVE.toInt(), `is`(Status.ACTIVE.code))
    }

    @Test
    fun fromIntToInactiveStatus() {
        assertThat(Status.INACTIVE.toInt(), `is`(Status.INACTIVE.code))
    }

    @Test
    fun fromIntToCompletedStatus() {
        assertThat(Status.COMPLETED.toInt(), `is`(Status.COMPLETED.code))
    }

    @Test
    fun fromActiveStatusToInt() {
        assertThat(Status.ACTIVE.fromInt(), `is`(Status.ACTIVE))
    }

    @Test
    fun fromInactiveStatusToInt() {
        assertThat(Status.INACTIVE.fromInt(), `is`(Status.INACTIVE))
    }

    @Test
    fun fromCompletedStatusToInt() {
        assertThat(Status.COMPLETED.fromInt(), `is`(Status.COMPLETED))
    }
}

I'm not super familiar with java kotlin interop, but is there any way to have these extensions as your TypeConverters?

EDIT:

Beware as @Luksprog pointed out in his answer, the Status.fromInt() extension method isn't a correct converter method. It would instead have to be an extension on Int. I've edited my question to show this.

First of all, one of the extension methods(fromInt()) isn't a real converter method. For that method Room expects a method in the form of(in java):

static Status fromInt(int code){...}

however the Kotlin compiler will generate(in java) something like

static Status fromInt(Status obj){...}

Room will not know what to do with this method which it needs to convert from the int in the database to your Status field.

Secondly, in their current form, those two extension methods are pretty useless. One is an alias for Status.ACTIVE.code and the other will simply return the instance on which is invoked.

You can't use those methods for the TypeConverters interface because that interface expects a class reference which groups the required static methods. You can't access in kotlin the java class(containing the methods) which will be generated by the kotlin compiler so you can't use it on the database.

If you want to keep your current extension methods but also create the required type converters methods you could use some indirection like below:

fun Status.toInt(): Int = StatusConverters.toInt(this)

fun Status.fromInt(): Status = StatusConverters.fromInt(this.code)

object StatusConverters {
    @TypeConverter
    @JvmStatic
    fun toInt(status: Status): Int = status.code // This could be shorter I know

    @TypeConverter
    @JvmStatic
    fun fromInt(code: Int): Status = when (code) { // This could also be shorter
       Status.ACTIVE.code -> Status.ACTIVE
       Status.INACTIVE.code -> Status.INACTIVE
       Status.COMPLETED.code -> Status.COMPLETED
       else -> {
            Timber.e("Could not recognize Status")
            throw IllegalArgumentException("Could not recognize Status")
       }
    }
}
  • 1
Reply Report