Gradle project does not build when I add RoboBlend

2019-07-06 08:19发布

问题:

I have added RoboGuice 3 dependency into my gradle build file it compiles and runs, however the application crashes because of NoClassDefFoundError: AnnotationDatabaseImpl. Did some research that suggested that RoboBlender was necessary to generate the definition (I'm familiar with RoboGuice 2 which does not require RoboBlender) but when I add RoboBlender the project no longer builds.

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.3'
compile 'com.android.support:cardview-v7:21.0.+'
compile 'com.android.support:recyclerview-v7:21.0.+'
compile 'com.koushikdutta.urlimageviewhelper:urlimageviewhelper:1.0.4'
compile 'de.hdodenhof:circleimageview:1.2.1'
compile 'com.getbase:floatingactionbutton:1.4.0'
compile 'de.hdodenhof:circleimageview:1.2.1'
compile 'org.twitter4j:twitter4j-core:4.0.2'
compile files('libs/json-me.jar')
compile files('libs/twitter_api_me-1.9.jar')
compile('ch.acra:acra:4.5.0') {
    exclude group: 'org.json'
}
compile 'org.roboguice:roboguice:3.0.1'
provided 'org.roboguice:roboblender:3.0.1'

}

Build Error:

 Error:Execution failed for task ':app:compileDebugJava'.

java.lang.ClassCastException: com.sun.tools.javac.code.Type cannot be cast to javax.lang.model.type.DeclaredType l>

  • Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.) Re-download dependencies and sync project (requires network)
  • The state of a Gradle build process (daemon) may be corrupt. Stopping all Gradle daemons may solve this problem. Stop Gradle build processes (requires restart)
  • In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.

    Whats causing this and how can I fix it?

    回答1:

    This kind of error can be caused by using @Inject incorrectly as in the following example:

    public class Foo {
    
        @Inject
        public Foo(Context context, int code) { 
            //this won't work because of the primitive in the constructor 
            //and the @Inject annotation are being used together
        }
    
    }
    

    RoboBlender will not be able construct the database because of being unable to cast the primitive as a declared type.

    Hence, your error message

    java.lang.ClassCastException: com.sun.tools.javac.code.Type cannot be cast to javax.lang.model.type.DeclaredType
    

    means that the primitive (com.sun.tools.javac.code.Type) cannot be cast into a reference type javax.lang.model.type.DeclaredType

    Instead, you need to write a Provider:

    public class FooProvider implements Provider<Foo> {
    
        Context context;
        private static int CODE = 1;
    
        @Inject
        public FooProvider(Context context) {
            this.context = context;
        }
    
        @Override
        public Foo get() {
            return new Foo(context, CODE);
        } 
    }
    

    and bind Foo to that provider in the module

    binder.bind(Foo.class).toProvider(FooProvider.class);

    and remove the @Inject from the constructor of Foo.

    I suggest you traverse your object graph and look for @Inject annotations on constructors with primitives in them. Delete the annotations and write providers for them as above. RoboBlender will correctly build the AnnotationsDatabaseImpl and your project will compile.



    回答2:

    Well I found a workaround, I just disabled AnnotationDatabase processing and removed RoboBlender dependency and that fix my problem. I would still like to know why I'm having this problem in the first place.



    回答3:

    I had the same issue and in my case, having a class with 2 constructors:

    @Inject
    public PaymentSelectionDialog(Context context) {
        this.context = context;
    }
    
    @Inject
    public PaymentSelectionDialog(Context context, PaymentSelectable paymentSelectable) {
            this.context = context;
            this.paymentSelectable = paymentSelectable;
    

    I had no problems using first constructor, but when I was instantiating my object using second constructor i have that problem. So the problem is that Roboguice is trying to inject an object that implements PaymentSelectable interface but this object is not defined in any module.

    Maybe you are using a constructor with a reference that you are not defining in any of your modules.

    Hope it helps!