Question

How can you combine modules with no no-args constructor. I have a library containing multiple modules, which I want to reuse in my apps. However, these modules require some parameters. The following example describes my setup:

Library:

@Module(
    library = true
)
public class LibModule1 {

    private final String mString;

    public LibModule1(String string) {
        mString = string;
    }
    //... provide methods 
}

@Module(
    library = true,
    addsTo = LibraryModule1.class
)
public class LibModule2 {

    private final String mString;

    public LibModule2(String string) {
        mString = string;
    }
    //... provide methods 
}

Notice that LibModule2 depends on some provided objects from LibModule1.

App: In my app I inject objects from LibModule1 and LibModule2 into one class. But I don't know, how I can combine these modules. The includes parameter doesn't work, since both modules have no no-args constructor. addsTo doesn't work, because I need both library modules, but the parameter let's me only set one class. Creating two app modules injecting my class MyClass.class doesn't work (a class can only be injected by one module, right?!).

@Module(
    injects = MyClass.class
)
public class AppModule {

}

How can I solve this issue?

Était-ce utile?

La solution

You are entirely free to pass in live instances of modules to ObjectGraph.create() and graph.plus(). If you have stateful modules, you should do things like:

ObjectGraph graph = 
    ObjectGraph.create(new LibraryModule1("foo"), LibraryModule2("bar));

That said, if you instantiate the library modules you describe in your question this way they will still fail at compile-time, as they unless you include each other (or mark complete-false). You can simply have LibModule2 include LibModule1, since you say it has objects which depend on objects provided by the latter.

@Module(library = true)
public class LibModule1 {

  private final String mString;

  public LibModule1(String string) {
    mString = string;
  }
  //... provide methods 
}

@Module(includes = LibraryModule1.class)
public class LibModule2 {

  private final String mString;

  public LibModule2(String string) {
    mString = string;
  }
  //... provide methods 
}

I would recommend against complete=false in the scenario you describe in your question, so you don't end up avoiding graph analysis. You should only use complete=false in the case that you are creating a reusable module that expects graph state it cannot include directly via another module, because it will be combined with a module whose identity is unknown at compile-time.

You should only do what you're doing here if you plan on using LibModule2 in the context of alternatives to LibModule1. In the case above, there is no particular reason to not include LibModule1 from LibModule2.

complete=false modules are excluded from all graph analysis, because they do not assert their completeness. But both of these modules can be complete, if the inclusion is given. But you must pass these modules in as instances, because they have no no-args constructors.

You should only use library=true to indicate that some of the bindings provided are provided for consumption by other dependencies, and not to be obtained via graph.get(Foo.class) as entry points to the graph. Essentially, library=true modules are excluded from orphan binding analysis.

Autres conseils

I'm sorry, I did something wrong. Now it works.

Answering my own question: You need to include the library modules.

@Module(
    injects = MyClass.class,
    includes = {LibModule1.class, LibModule2.class}
)
public class AppModule {

}

In one module I was missing a complete = false parameter.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top