Dagger: Hilt: More meaningful error messages

Created on 3 Jul 2020  路  16Comments  路  Source: google/dagger

First of all, Hilt looks like a really promising project, keep up the good work!

One feature I would like to see is more meaningful error messages at run time and compile time. For instance, one error I always seem to get is:

Caused by: java.lang.ClassCastException: com.mypackage.DaggerMainApplication_HiltComponents_ApplicationC$ActivityRetainedCImpl$ActivityCImpl cannot be cast to com.com.mypackage.MyActivity_GeneratedInjector

This runtime exception basically means that there is an error in the dependency graph meaning something can't be injected, but it would be nice to know what exactly.

Even better, if this problem could be caught and displayed at compile time, then fantastic :)

kind regards,
goldy1992

hilt

Most helpful comment

i just got an error and all it said was [Hilt] lol

All 16 comments

Hm, usually that error shouldn't be so easy to hit. That should only happen if somehow we're not picking up your @AndroidEntryPoint class correctly from the classpath. Is your build structured in a way that your @HiltAndroidApp class does not have that @AndroidEntryPoint class as a transitive dependency?

@Chang-Eric Regarding that error, I should mention that it was very much resolved by manually doing a gradle build before running the application in Android Studio. There was actually a compile time error.
This leads me to believe that there is an issue with Android Studio not rebuilding some Hilt (dagger) code that has changed since the last deployment.

Thanks, we'll need to look into that. I know it has been a few days, so completely understand if you don't remember, but if you happen to remember where the compile error was that would be useful for us trying to repro. For example, was it a compile error in your @AndroidEntryPoint class or just an unrelated file?

Hey, I just add the same issue.
In my project, I have an interface Logger used to log stuffs, and its implementation TimberLogger (injected via constructor)
TimberLogger is provided using a module:

@Module
@InstallIn(ApplicationComponent::class)
abstract class BoundaryModule {

    @Binds
    abstract fun bindLogger(impl: TimberLogger): Logger
}

When building with Android Studio, the application crashes with at runtime with this stacktrace:

java.lang.NoClassDefFoundError: Failed resolution of: Lexample/core/Logger;
        at example.app.DaggerFooApplication_HiltComponents_ApplicationC.builder(DaggerFooApplication_HiltComponents_ApplicationC.java:84)
        at example.app.Hilt_FooApplication$1.get(Hilt_FooApplication.java:21)
        at dagger.hilt.android.internal.managers.ApplicationComponentManager.generatedComponent(ApplicationComponentManager.java:40)
        at example.app.Hilt_FooApplication.generatedComponent(Hilt_FooApplication.java:33)
        at example.app.Hilt_FooApplication.onCreate(Hilt_FooApplication.java:41)
        at example.app.FooApplication.onCreate(FooApplication.kt:26)
        at example.app.DebugFooApplication.onCreate(DebugFooApplication.kt:12)
        at android.app.Instrumentation.callApplicationOnCreate(Instrumentation.java:1192)

(It's broken on all latest AS version for each track.)

While building it manually with the gradle wrapper works just fine.

Thanks, we'll need to look into that. I know it has been a few days, so completely understand if you don't remember, but if you happen to remember where the compile error was that would be useful for us trying to repro. For example, was it a compile error in your @AndroidEntryPoint class or just an unrelated file?

Yes this is a compilation error of a dependency related to a class annotated with @AndroidEntryPoint. Once the error is fixed and you manually do a gradle build it will work fine.

To be honest the compile time error is very explanatory, so I guess the real issue is getting android studio to detect a change before and do the build automatically before the deployment is triggered.

(It may already have this functionality and I just need to activate something within the Android Studio settings). Feel free to change the title of the issue accordingly

@goldy1992, quick question, what Android Studio (and Android Studio Plugin) version were you using when you encountered your original issue (The ClassCastException one)?

i just got an error and all it said was [Hilt] lol

@martipello if you can, can you copy the whole message? I wonder if the message got kicked to another line below or something.

@danysantiago the hilt-android-gradle-plugin was 2.28-alpha.

Sorry, not the Hilt plugin, I meant the Android Gradle Plugin, the version of your com.android.tools.build:gradle along with your version of Android Studio.

@danysantiago 4.0.0

@Chang-Eric, is it expected to occur in below scenario?

:ui-component module - 'com.android.library'
:profile module - 'com.android.library'

implementation project(':ui-component')

:app module - 'com.android.application'

implementation project(':ui-component')
implementation project(':profile')

In the above project, I have my Application class in :ui-component module.

@HiltAndroidApp
class CommonApp : Application()

And my Activity is in :profile module.

@AndroidEntryPoint
class ProfileActivity : BaseActivity(R.layout.activity_profile)

But when I run this app, I get below exception at runtime.

Process: com..., PID: 11338
    java.lang.RuntimeException: Unable to start activity ComponentInfo{.../....ProfileActivity}: java.lang.ClassCastException: ....DaggerCommonApp_HiltComponents_ApplicationC$ActivityRetainedCImpl$ActivityCImpl cannot be cast to ...ProfileActivity_GeneratedInjector
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2666)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1478)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6123)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)
     Caused by: java.lang.ClassCastException: ....DaggerCommonApp_HiltComponents_ApplicationC$ActivityRetainedCImpl$ActivityCImpl cannot be cast to ...ProfileActivity_GeneratedInjector
        at ....Hilt_ProfileActivity.inject(Hilt_ProfileActivity.java:56)
        at ....Hilt_ProfileActivity.onCreate(Hilt_ProfileActivity.java:31)
        at ....ProfileActivity.onCreate(ProfileActivity.kt:25)
        at android.app.Activity.performCreate(Activity.java:6723)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2619)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727)聽
        at android.app.ActivityThread.-wrap12(ActivityThread.java)聽
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1478)聽
        at android.os.Handler.dispatchMessage(Handler.java:102)聽
        at android.os.Looper.loop(Looper.java:154)聽
        at android.app.ActivityThread.main(ActivityThread.java:6123)聽
        at java.lang.reflect.Method.invoke(Native Method)聽
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)聽
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779)聽

What could go wrong here? And why it's a runtime error instead of compile time?

@ChanSek, :ui-component module must have a dependency on :profile in order for it to handle the @AndroidEntryPoint activity in :profile.

The reason is that @HiltAndroidApp generates the components for Hilt, so anything you want to be included in the components (e.g. @InstallIn modules and entry points and @AndroidEntryPoint usages) has to be in the transitive dependencies of the Gradle module with @HiltAndroidApp.

It would be difficult for us to make this a compile time error. Basically, the issue is that neither of the Gradle modules know about each other when they are compiled because neither are dependencies of the other.

@bcorso, that's my bad. I forgot to mention that, my :profile module's build.gradle has below dependency.

implementation project(':ui-component')

So ideally it should work without the error. I have also updated the above comment accordingly.

@ChanSek IIUC, it would have to be the opposite. In particular, :ui-component contains the @HiltAndroidApp, so it would have to have a dependency on :profile.

I think the original issue is likely a duplicate of #2139, so I'll close this issue for that one.

Was this page helpful?
0 / 5 - 0 ratings