Room TypeConverter with constructer

北战南征 提交于 2020-12-29 06:35:48

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!