google/dagger

Feature request: Manually regenerate application component

marcorighini opened this issue · 1 comments

We need to regenerate the application component manually on logout (i.e. the singleton dependencies).

This is due to several singleton dependencies with state variables related to the logged-in user. This makes it hard and error-prone to follow solutions like resetting those dependencies or using custom components (this would also require writing all the boilerplate associated with entrypoints).

Investigating the generated Hilt code we found that the following code would provide such a feature

@HiltAndroidApp
class LogApplication : Application() {

    @Inject
    internal lateinit var dependency: LoggerInMemoryDataSource

    override fun onCreate() {
        super.onCreate()
        logout()
    }

    @Suppress("CAST_NEVER_SUCCEEDS")
    private fun regenerateComponent() {
        Log.d("", "Before: $dependency")

        val cm = (this as GeneratedComponentManagerHolder).componentManager()
        val f = ApplicationComponentManager::class.java.declaredFields.find { it.name == "component" }
        f?.let {
            it.isAccessible = true
            f.set(cm, null)
        }
        ((this as GeneratedComponentManager<ApplicationComponentManager>)
            .generatedComponent() as LogApplication_GeneratedInjector)
            .injectLogApplication(UnsafeCasts.unsafeCast(this))

        Log.d("", "After: $dependency")
    }

    fun logout() {
        regenerateComponent()
    }
}

We tested it and LoggerInMemoryDataSource (a singleton) reference is changing.

Our questions are the following:

  • do you see any drawback of the previous solution apart from the need for testing on every Hilt upgrade?
  • the feature does not seem so hard to support by Hilt, does it make sense to provide it officially? The use case should not be so uncommon.

Thanks!