A dagger cannot create an object graph, although it can create a point file

I am struggling with installing Dagger (1.0.1) in an existing application. It was configured to use ProGuard, but I disabled it for this test using -dontobfuscate .

When I turn on the king compiler, it can successfully generate a dot file with a dependency graph, but when I remove the compiler and create the application in Release mode, it crashes at startup, complaining that it cannot create an object graph.

 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.corp.myapp/com.corp.myapp.ui.activity.MainActivity}: java.lang.IllegalStateException: Errors creating object graph: No injectable members on com.corp.myapp.core.services.ConnectionMonitor. Do you want to add an injectable constructor? required by com.corp.myapp.core.services.ConnectionMonitor com.corp.myapp.ui.activity.MyAppBaseActivity.connectionManager No injectable members on com.corp.myapp.ui.crouton.CroutonManager. Do you want to add an injectable constructor? required by com.corp.myapp.ui.crouton.CroutonManager com.corp.myapp.ui.activity.MyAppBaseActivity.croutonManager No injectable members on com.corp.core.assembler.ResourceAssembler. Do you want to add an injectable constructor? required by com.corp.core.assembler.ResourceAssembler com.corp.myapp.ui.activity.MyAppBaseActivity.resourceAssembler 

I see MyAppBaseActivity and its dependencies on CroutonManager or ConnectionMonitor displayed in the generated point file, so according to this comment, I expected it to be Work. AFAIK, if something is wrong, it should be detected by the assembly with the compiler turned on, which I used to create the point file.


UPDATE:

I previously argued that

In debug mode it will never work

but this is not entirely true after further testing: in Debug mode it does not crash because ProGuard is disabled, while in Release mode it is enabled by default. If I create the application in Release mode, but skip ProGuard , I will not get errors and the application will start successfully. Therefore, the problem is definitely related to my ProGuard configuration.

+5
source share
4 answers

The dagger relies heavily on reflections and class names that are hard-coded and manipulated as strings. This makes code compression / optimization / obfuscation difficult.

The following configuration works for a sample dagger / examples / simple in Dagger 1.1.0 :

 -keepattributes *Annotation* -keepclassmembers,allowobfuscation class * { @javax.inject.* *; @dagger.* *; <init>(); } -keep class **$$ModuleAdapter -keep class **$$InjectAdapter -keep class **$$StaticInjection -keepnames !abstract class coffee.* -keepnames class dagger.Lazy 

The configuration saves all fields and methods with javax.inject or dagger annotations and all constructors without parameters. ProGuard may otherwise remove them if they appear unused, but the Dagger actually enters / accesses them through reflection. This is similar to RoboGuice.

It should also contain all adapter classes created by Dagger.

It should also contain all the class names associated with these adapter classes, so the names still match. In this example, these are almost all the classes in the coffee package, so the easiest way is to use wild-card. This line will be different for other applications.

Finally, it should also contain the class name dagger.Lazy , since its name is hard-coded as a string in the generated code.

+17
source

The dagger does not require @Inject be in the class, which must be passed to graph.inject(myActivity) , because some actions may not have any injections. However, they appear to be dependent on the upstream, which means that they must be provided by ComponentInfo and therefore must be provided by a dagger. He cannot do this if he cannot create these classes, and he cannot do this unless they are annotated, unless they provide them using the @Provides method.

So, you need to create an @Module -annotated class that returns these types from @Provides -independent methods, or you need to add @Inject to your constructor.

 -keep class * extends dagger.internal.Binding 

In this case, are you using proguard in release mode? And not in debug mode? If so, I suspect Proguard is taking annotations. You will need to make several options:

 -keep class javax.inject.** { *; } 

... so that Proguard does not delete annotations.

+1
source

I got the application to run after adding -dontshrink to the ProGuard configuration file. It is not enough to have -dontobfuscate at the beginning.

In fact, if I -dontobfuscate , it also works.

I definitely need finer control, but this is the starting point. My current ProGuard dagger setting:

 ############# # Dagger # ############# -keep class dagger.** { *; } -dontwarn dagger.internal.codegen.** 
+1
source

I ended up burning week + trying to get this to work. In the end, I failed and decided to give DexGuard a shot. It worked great right out of the box. Yes, this is a commercial product, but DexGuard has a lot of support, and because of this, we were finally able to go. Id definitely recommends DexGuard if you absolutely need to solve this problem.

0
source

All Articles