【问题标题】:Room TypeConverter with constructer带有构造函数的房间类型转换器
【发布时间】:2019-04-06 11:05:30
【问题描述】:

我有 Room TypeConverter,我需要向它的构造函数注入参数

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)}
    }
}

但是当我无法使用构造函数将TypeConverter 注释到数据库对象时;

@Database(entities = [SsidModel::class], version = 1, exportSchema = false)
@TypeConverters(RoomConverters::class)   
abstract class AppDatabase : RoomDatabase() {

    abstract fun ssidDao(): SsidDao
}

有什么办法可以做到吗?

【问题讨论】:

    标签: android kotlin android-room


    【解决方案1】:

    您可以使用 2.3.0-alpha03

    版本的构造函数参数创建 Room TypeConverter

    发行说明:

    Room 现在有用于提供类型转换器实例的 API,例如 该应用程序可以控制它们的初始化。标记类型转换器 将提供给 Room 使用新注释 @ProvidedTypeConverter

    https://developer.android.com/jetpack/androidx/releases/room#2.3.0-alpha03

    在您的情况下,您应该将 @ProvidedTypeConverter 添加到 RoomConverter

    @ProvidedTypeConverter    
    class RoomConverters(moshi: Moshi)
    

    在创建数据库时创建转换器并将其传递给数据库构建器:

    val roomConverter = RoomConverters(Moshi())
    val db = Room.databaseBuilder()
             .addTypeConverter(roomConverter)
             .build()
    

    您也可以使用 DI 框架,例如匕首2

    【讨论】:

      【解决方案2】:

      现在 Room 库 2.3.0 已经发布。可以实例化 Room 类型转换器并将它们提供给数据库构建器。

      @ProvidedTypeConverter 注解添加到TypeConverter 类中。

      @ProvidedTypeConverter
      class RoomConverter(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)}
          }
      }
      

      在数据库抽象类的@TypeConverter注解中提及TypeConverter。

      @Database(entities = [/* entities here */], version = 1, exportSchema = false)
      @TypeConverters(RoomConverters::class)   
      abstract class AppDatabase : RoomDatabase() {
          ......
          // your code here
          ......
      }
      

      现在使用Room类的静态方法databaseBuilder构建数据库,并使用addTypeConverter()方法提供TypeConverter

      val roomConverter = RoomConverter(moshi)
      val appDb = Room.databaseBuilder(
                                  applicationContext,
                                  AppDatabase::class.java, DB_NAME
                              )
                                  .addTypeConverter(roomConverter)
                                  .build()
      

      【讨论】:

        【解决方案3】:

        我使用 dagger-android,遇到了同样的问题。 解决方案是在创建 AppDatabase 时

        @Provides @Reusable
        fun provideDatabase(context: Context, moshi: Moshi): AppDatabase = 
            Room.databaseBuilder(...).build().apply { AppDatabase.moshi = moshi }
        

        AppDatabase 是简单的 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
        }
        

        然后在转换器中使用这个伴随对象:

        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)
        }
        

        我猜这看起来很丑,但很有效。也许在@Reuseable 范围内使用静态/伴随对象是个坏主意。 不过,Moshi 是在 AppModule 中使用 @Singleton 范围提供的,所以基本上贯穿整个应用程序生命周期

        【讨论】:

          【解决方案4】:

          我甚至检查了最新的 rc 版本 (2.2.0-rc01) 的文档,但没有办法做到这一点。我认为我们无法在 DatabaseBuilder 中注册自定义 TypeConverters 是个笑话,所以我在 Google issue tracker 上为此创建了错误。

          【讨论】:

            【解决方案5】:

            截至 2020 年 8 月 11 日,Google 仍未解决此问题。同时检查这些解决方法之一。

            https://issuetracker.google.com/issues/142086380 https://issuetracker.google.com/issues/121067210

            【讨论】:

            • 2021 年 4 月 21 日发布的 Room 2.3.0 版现在支持此功能,谢天谢地。
            猜你喜欢
            • 1970-01-01
            • 2012-07-12
            • 1970-01-01
            • 1970-01-01
            • 2018-07-06
            • 2016-02-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多