Search code examples
androiddagger-hilt

How to Inject Moshi/Gson in Room TypeConvertors using Hilt?


I am trying out hilt and i want to inject moshi for serializing and deserializing.

Here's a code sample from a github Repo which is not using di:

open class InfoTypeConverter {

private val moshi = Moshi.Builder().build() //not using dependency injection

  @TypeConverter
  fun fromString(value: String): PokemonInfo.Type? {
    val adapter: JsonAdapter<PokemonInfo.Type> = moshi.adapter(PokemonInfo.Type::class.java)
    return adapter.fromJson(value)
  }

  @TypeConverter
  fun fromInfoType(type: PokemonInfo.Type): String {
    val adapter: JsonAdapter<PokemonInfo.Type> = moshi.adapter(PokemonInfo.Type::class.java)
    return adapter.toJson(type)
  }
}

I am Trying out random stuff to field inject this like annotaion with @AndroidEntryPoint/@EntryPoint and obviously it's not working.


Solution

  • Including Moshi in the Hilt dependency graph is as simple as adding this class:

    @Module
    @InstallIn(ApplicationComponent::class)
    object DataModule {
    
      @Singleton
      @Provides
      fun provideMoshi(): Moshi {
          return Moshi.Builder().build()
      }
    }
    

    @TypeConverters are for the Room database. If you want to use the Moshi from Hilt for them, you will have to try a bit. One way of doing this is:

    1. Put @TypeConverter functions in a static context (object declaration) with an initializer
    object InfoTypeConverter {
    
        private lateinit var moshi: Moshi
    
        fun initialize(moshi: Moshi){
            this.moshi = moshi
        }
    
        
        @TypeConverter
        fun fromString(value: String): PokemonInfo.Type? {
          val adapter: JsonAdapter<PokemonInfo.Type> = moshi.adapter(PokemonInfo.Type::class.java)
          return adapter.fromJson(value)
        }
    
        @TypeConverter
        fun fromInfoType(type: PokemonInfo.Type): String {
          val adapter: JsonAdapter<PokemonInfo.Type> = moshi.adapter(PokemonInfo.Type::class.java)
          return adapter.toJson(type)
        }
    }
    
    1. Initialize InfoTypeConverter before creating your RoomDatabase (here using the same module for the purpose):
    @Module
    @InstallIn(ApplicationComponent::class)
    object DataModule {
    
      @Singleton
      @Provides
      fun provideMoshi(): Moshi {
          return Moshi.Builder().build()
      }
    
      @Singleton
      @Provides
      fun provideRoomDatabase(moshi: Moshi): YourDatabase {
          InfoTypeConverter.initialize(moshi)
          val yourDatabase: YourDatabase = /* create your room database here */
          return yourDatabase
      }
    }