〈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 👩💻👨💻