问题
I have Room TypeConverter
and I need to inject parameter to it's constructor
class RoomConverters(moshi Moshi) {
@TypeConverter
fun fromUserActionLog(data: UserActionLogModel): String {
return moshi.adapter(UserActionLogModel::class.java).toJson(data)
}
@TypeConverter
fun toUserActionLog(json: String): UserActionLogModel {
return moshi.adapter(UserActionLogModel::class.java).fromJson(json)}
}
}
But when I can not annotate TypeConverter
to database object with contructor;
@Database(entities = [SsidModel::class], version = 1, exportSchema = false)
@TypeConverters(RoomConverters::class)
abstract class AppDatabase : RoomDatabase() {
abstract fun ssidDao(): SsidDao
}
Is there any way to achieve this?
回答1:
I use dagger-android, and faced same problem. Solution is when creating AppDatabase
@Provides @Reusable
fun provideDatabase(context: Context, moshi: Moshi): AppDatabase =
Room.databaseBuilder(...).build().apply { AppDatabase.moshi = moshi }
AppDatabase is simple RoomDatabase:
@Database(
entities = [OrderEntity::class],
version = 1,
exportSchema = false
)
@TypeConverters(DbConverters::class)
abstract class AppDatabase : RoomDatabase() {
companion object {
lateinit var moshi: Moshi
}
abstract fun orderDao(): OrderDao
}
Then use this companion object in converter:
class DbConverters {
@TypeConverter
fun orderInfoToString(orderInfo: OrderInfo?): String? =
AppDatabase.moshi.adapter(OrderInfo::class.java).toJson(orderInfo)
@TypeConverter
fun stringToOrderInfo(value: String): OrderInfo? =
AppDatabase.moshi.adapter(OrderInfo::class.java).fromJson(value)
}
This is looking ugly, I guess, but works. Maybe using static/companion object with @Reuseable
scope is a bad idea.
Moshi, though, is provided using @Singleton
scope in AppModule, so basically live through entire application life
回答2:
I checked documentation even for the newest rc version (2.2.0-rc01
) and there is no way to do that. I think it's a joke that we can't register custom TypeConverters in DatabaseBuilder, so I created bug for that on Google issue tracker.
回答3:
You can create Room TypeConverter with constructor parameters from version 2.3.0-alpha03
Release notes:
Room now has APIs for providing instances of type converters such that the app can control their initialization. To mark a type converter that will be provided to Room use the new annotation @ProvidedTypeConverter
https://developer.android.com/jetpack/androidx/releases/room#2.3.0-alpha03
In your case you should add @ProvidedTypeConverter to RoomConverter
@ProvidedTypeConverter
class RoomConverters(moshi: Moshi)
Create converter at db creation time and pass it to database builder:
val roomConverter = RoomConverters(Moshi())
val db = Room.databaseBuilder()
.addTypeConverter(roomConverter)
.build()
Also you can use DI framework e.g. Dagger2
回答4:
As of August 11th 2020 there's still no fix for this from Google. Check either of these workarounds in the meantime.
https://issuetracker.google.com/issues/142086380 https://issuetracker.google.com/issues/121067210
来源:https://stackoverflow.com/questions/53114573/room-typeconverter-with-constructer