Search code examples
androidunit-testingkotlindependency-injectiondagger-2

Dagger singleton vs Kotlin object


To define a singleton, should I use Kotlin object declaration or to make an ordinary Kotlin class and inject it using dagger? In my opinion the first option is definitely easier but there may be a reason to use dagger in this situation that I'm not aware of.

Option 1 (notice object keyword):

object SomeUtil {
    // object state (properties)

    fun someFunction(number: Long) {
        // ...
    }
}

Option 2 (notice class keyword):

class SomeUtil {
    // object state (properties)

    fun someFunction(number: Long) {
        // ...
    }
}
@Module
class AppModule {

    @Provides
    @Singleton
    internal fun provideTheUtil() = SomeUtil()
}
class MainActivity : BaseActivity() {

    @Inject internal lateinit var util: SomeUtil
}

UPDATE 2019-07-03

@Blackbelt said in comments that we should prefer option 2 for testability. But libraries like MockK can mock objects too. So do you still think option 2 is the preferred one?


Solution

  • You might want to reconsider the need of NumberFormatUtil being a singleton. It might be cheaper if you use @Reusable with Dagger or even a factory without any scope directly.

    If NumberFormatUtil is fairly simple and only provides a few utility methods, no state and no need for mocking in tests, you could use an object implementation, maybe using @JvmStatic for Java-inter-operability. But then you could go for global utility (extension) functions as well:

    package xyz
    
    fun formatNumber(number: Long) {
        // ...
    }
    
    fun Long.format() = formatNumber(this)