〈kotlin〉 Roomでサポートされていない型を保存する(TypeConverter)

Android studioでkotlinを使ってAndroidアプリ作成の勉強中。

Roomについて。
mtnmr.hatenablog.com

Roomはプリミティブ型(Int, String, Booleanとか基本の型)の保存をサポートしているが、
それ以外の型でもTypeConverterを使えば保存できそうだったのでやってみる。

Room を使用して複雑なデータを参照する  |  Android デベロッパー  |  Android Developers
公式ドキュメントを参考に、Date型を保存できるようにする。
レイアウトにEditText, Button, RecyclerViewを用意し、
Buttonを押すとEditTextに入力した単語とその日時をRoomに保存、
保存したデータはRecyclerViewに一覧表示されるサンプルアプリを作って試した。

Entity

@Entity
data class Item(
    @PrimaryKey(autoGenerate = true) val id:Int = 0,
    val ItemText: String,
    val createdAt: Date?
)

TypeConverter

Roomが永続化できる既知の型とカスタム型との間での変換方法を Room に伝えるメソッドを定義。
この例では、
・Date型 → Roomに保存できるLong型への変換
・Long型 → Date型へ戻す変換
の2つのメソッドを作成している。

class DateConverter {
    @TypeConverter
    fun fromTimeStamp(value: Long?): Date? {
        return value?.let { Date(it) }
    }

    @TypeConverter
    fun dateToTimeStamp(date:Date?): Long?{
        return date?.time?.toLong()
    }
}

RoomDatabase

Databaseには@TypeConvertersアノテーションを追加して、
定義したコンバータクラスをRoomが認識できるように登録する。

@Database(entities = [Item::class], version = 1)
@TypeConverters(DateConverter::class)
abstract class AppDatabase : RoomDatabase() {
  abstract fun itemDao(): itemDao
}

あとはViewModel内とかで取得したDate型をそのまま保存するだけ。

fun saveItem(text:String){
    viewModelScope.launch {
        if(text != ""){
           itemDao.saveItem(Item(ItemText = text, createdAt = Date()))
        }
    }
}

TypeConverterに依存関係を渡したいとき

RoomがTypeConverterのインスタンス化をしているが、
TypeConverterに引数として依存関係を渡す場合はインスタンス化できない。
そのため自分でTypeConverterの初期化を制御する。

//クラスにアノテーションをつける
@ProvidedTypeConverter
class ExampleConverter(hoge: Hoge) {
  @TypeConverter
  fun StringToExample(string: String?): ExampleType? {
    ...
  }

  @TypeConverter
  fun ExampleToString(example: ExampleType?): String? {
    ...
  }
}
//Hogeを渡したインスタンスを作成
val exampleConverterInstance = ExampleConverter(Hoge())
//RoomDatabaseビルダーにコンバータクラスのインスタンスを渡す。
val db = Room.databaseBuilder(...)
  .addTypeConverter(exampleConverterInstance)
  .build()

以下の記事がわかりやすくて参考にした。
Room - Provided Type Converters explained - DEV Community 👩‍💻👨‍💻