13
votes

I am trying to get Room(https://developer.android.com/topic/libraries/architecture/room) work with Kotlin's inline classes as described in Jake Whartons article Inline Classes Make Great Database IDs:

@Entity
data class MyEntity(
    @PrimaryKey val id: ID,
    val title: String
)

inline class ID(val value: String)

When compiling this Room complains that

Entities and Pojos must have a usable public constructor. You can have an empty constructor or a constructor whose parameters match the fields (by name and type).

Looking into the generated Java code I find:

private MyEntity(String id, String title) {
      this.id = id;
      this.title = title;
}

// $FF: synthetic method
public MyEntity(String id, String title, DefaultConstructorMarker $constructor_marker) {
      this(id, title);
}

Mysteriously the default constructor is private now.

When using String as a type for id (or a typealias), the generated Java class constructor looks like expected:

public MyEntity(@NotNull String id, @NotNull String title) {
  Intrinsics.checkParameterIsNotNull(id, "id");
  Intrinsics.checkParameterIsNotNull(title, "title");
  super();
  this.id = id;
  this.title = title;
}

Does somebody now how to keep the default constructor public while using Inline Classes as data entity properties?

2
Did you rise an issue for this on some issue tracker? I guess this need to be clarified for sureK.Os
What is the Room version? The latest stable one is 2.3.0 and the latest one is 2.4.0-alpha02 at the time I'm commenting.Dr.jacky

2 Answers

0
votes

I believe the reason is that the ID class will be represented as String in runtime. So the $constructor_marker additional parameter is to guarantee the uniqueness of the MyEntity(String id, String title) constructor signature, cause this constructor could already have been defined. But I'm just speculating here.

Could you try to explicitly define this constructor in MyEntity class and see if it works?

0
votes

Kotlin inline classes use name mangling.

So I believe your Room database cannot find the getter and setter for you ID field. Try to add:

...
@get:JvmName("getID")
@set:JvmName("setID")
@PrimaryKey val id: ID,

before your ID parameter declaration to disable mangling. It helps to me