Search code examples
javaandroiddependency-injectionroboguiceassisted-inject

Android assisted injection with Factory using Roboguice not working


I'm trying to inject some classes while passing some parameters in the constructor. To achive that, I've found this questions (1, 2) saying that this could be achived by using Assisted Injection with a Factory. This is how my code looks like, following the examples provided and some modifications after reading the related documentation.

gradle script

dependencies { 
    compile 'org.roboguice:roboguice:3.+'
    provided 'org.roboguice:roboblender:3.+'
    compile 'com.google.inject.extensions:guice-assistedinject:3.+' 
}

Factory interface with create method that accepts parameters

public interface ICustomObjectFactory {
    ICustomObject create(Callback callback);
}

Class that implements the interface

public class CustomObject implements ICustomObject {
    protected String name;

    @AssistedInject
    public CustomObject(@Assisted Callback callback){
       this.callback = callback;
    }
}

Module used and called from the Aplication class

public class SomeModule extends Module {

    @Override
    protected void configure() {
         install(new FactoryModuleBuilder()
            .implement(ICustomObject.class, CustomObject.class)
            .build(ICustomObjectFactory.class));
    }
}

Injection Module registered from the Application class

@Override
public void onCreate() {
    super.onCreate();

    RoboGuice.getOrCreateBaseApplicationInjector(this, RoboGuice.DEFAULT_STAGE,
            RoboGuice.newDefaultRoboModule(this), new SomeModule(this));
}

Use of the Factory

public class SomeClass implements Callback {

    @Inject ICustomObjectFactory factory;

    public SomeClass () {
        ICustomObject first = this.factory.create(this);
    }
}

With all like this, I'm getting this error when I try to use the factory, as it's been used in SomeClass

java.lang.IllegalStateException: Factories.create() factories cannot be used until they're initialized by Guice.
        at com.google.inject.internal.util.$Preconditions.checkState(Preconditions.java:142)
        at com.google.inject.assistedinject.FactoryProvider2.getBindingFromNewInjector(FactoryProvider2.java:564)
        at com.google.inject.assistedinject.FactoryProvider2.invoke(FactoryProvider2.java:625)
        at java.lang.reflect.Proxy.invoke(Proxy.java:397)
        at $Proxy12.create(Unknown Source)

Someone knows why the Factory it's no initialized? I understand that should be initialized by the module, and I'm sure that the module it's been called.

The most remarcable difference between my code and the code from the questions linked is that in the questions, the constructor is annotated with @Inject, not @AssistedInject. Before this modification, I was getting this error compiling the app.

Error:Execution failed for task ':app:compileDebugJavaWithJavac'. java.lang.ClassCastException: com.sun.tools.javac.code.Type cannot be cast to javax.lang.model.type.DeclaredType dle'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)
  • Your project may be using a third-party plugin which is not compatible with the other plugins in the project or the version of Gradle requested by the project.
  • In the case of corrupt Gradle processes, you can also try closing the IDE and then killing all Java processes.

    Maybe this isn't the best approach to achieve what I need. If it isn't, could someone point me the right direction?

    Thank you all for your help


    Solution

  • At the end, I make it work by adding RoboGuice.setUseAnnotationDatabases(false) in the Application class:

    @Override
    public void onCreate() {
        super.onCreate();
    
        RoboGuice.setUseAnnotationDatabases(false);
        RoboGuice.getOrCreateBaseApplicationInjector(this, RoboGuice.DEFAULT_STAGE,
                RoboGuice.newDefaultRoboModule(this), new SomeModule(this));
    }