Closed ayoubdevv closed 4 years ago
Hey @ayoubdevv,
Thanks for reporting this issue!
This is definitely a bug on our end. We shouldn't be including the type parameters in @OriginatingElement(topLevelClass = BaseFragment<T, D>.class)
. I'll send out a fix.
In the mean time, you should be able to work around this issue by putting the @AndroidEntryPoint
annotation on the subclass instead. So something like this should work around the issue since the subclass doesn't have type parameters itself.
// Put the annotation here instead of on the base class.
@AndroidEntryPoint
class MyFragment: BaseFragment<MyViewModel, MyViewDataBinding>() {
...
}
thanks @bcorso for reply i'll try it but what about injecting ViewModel when using by viewModels() extension it says : Cannot use 'T' as reified type parameter. Use a class instead. Type 'Lazy' has no method 'setValue(BaseFragment<T, D>, KProperty<*>, T)' and thus it cannot serve as a delegate for var (read-write property).** do i need to inject each ViewModel in subclass also ?
thanks in Advanced @bcorso
it says : Cannot use 'T' as reified type parameter. Use a class instead.
I think this is just a restriction of Kotlin? Is this a pattern you were using before Hilt?
Edit: I know very little Kotlin, so happy to be proven wrong on this.
i just used like documentation here but didn't work so i used just ViewModelProvider i think the problem is in extension fuction itself
Thinking about this more, I think we need to ban @AndroidEntryPoint
for base classes with type parameters -- the workaround in https://github.com/google/dagger/issues/2042#issuecomment-673078030 being the preferred solution.
I'll fix the original bug, and then add a better error message to make it clear this isn't allowed.
Details:
The main issue is that @AndroidEntryPoint
needs to generate an injector for the annotated class, e.g. void inject(BaseActivity<T> activity)
, but Dagger can't inject the class with out knowing the explicit type which isn't available until a subclass extends it.
@bcorso what about this workaround when we can use it ?
@AndroidEntryPoint(BaseFragment::class)
class ExampleFragment : BaseFragment<FragmentExampleBinding>()
That should work out of the box already, but the usage above is not quite right.
If you're using the Hilt Gradle plugin you would just do this:
@AndroidEntryPoint
class ExampleFragment extends BaseFragment<FragmentExampleBinding>()
Yes it working when removing @AndroidEntryPoint from BaseFragment and put in subclass but base classes with type parameters we need it will be fixed or ban forever , because i used to use Dagger 2 and was work perfectly realyl thanks @bcorso for you're help it really Appreciated
@ayoubdevv @bcorso Maybe you can do this:
@AndroidEntryPoint abstract class HiltFragment : Fragment() { }
and
abstract class HiltBaseFragment<T : ViewDataBinding, V : BaseViewModel> : HiltFragment() {
thats work for me
@ghozimahdi not work for me
@AndroidEntryPoint abstract class HiltFragment : DialogFragment()
abstract class BaseDialogFragment
Hey @ayoubdevv,
Thanks for reporting this issue!
This is definitely a bug on our end. We shouldn't be including the type parameters in
@OriginatingElement(topLevelClass = BaseFragment<T, D>.class)
. I'll send out a fix.In the mean time, you should be able to work around this issue by putting the
@AndroidEntryPoint
annotation on the subclass instead. So something like this should work around the issue since the subclass doesn't have type parameters itself.// Put the annotation here instead of on the base class. @AndroidEntryPoint class MyFragment: BaseFragment<MyViewModel, MyViewDataBinding>() { ... }
@bcorso I can't use this work around if using multi-modules. I put BaseFragment in :base module. And other features module will implement this :base. And it will throw "failed to analyze: java.lang.reflect.InvocationTargetException" at compile time. Any updates on this?
Any updates on this?
The update is in https://github.com/google/dagger/issues/2042#issuecomment-673252618
I can't use this work around if using multi-modules. I put BaseFragment in :base module. And other features module will implement this :base. And it will throw "failed to analyze: java.lang.reflect.InvocationTargetException" at compile time.
By "multi-modules" do you mean you are using dynamic feature modules? If so, you're correct that you can't use Hilt in such a way. The guidance is explained in https://developer.android.com/training/dependency-injection/hilt-multi-module#dfm.
If you just mean normal Gradle modules, it shouldn't matter if BaseFragment
is in a separate module or not. If this is the case you can provide more details or if you can give a minimal reproducible example I can take a look to see why it might be failing.
Any updates on this?
The update is in #2042 (comment)
I can't use this work around if using multi-modules. I put BaseFragment in :base module. And other features module will implement this :base. And it will throw "failed to analyze: java.lang.reflect.InvocationTargetException" at compile time.
By "multi-modules" do you mean you are using dynamic feature modules? If so, you're correct that you can't use Hilt in such a way. The guidance is explained in https://developer.android.com/training/dependency-injection/hilt-multi-module#dfm.
If you just mean normal Gradle modules, it shouldn't matter if
BaseFragment
is in a separate module or not. If this is the case you can provide more details or if you can give a minimal reproducible example I can take a look to see why it might be failing.
I just used normal android library modules. I created a sample that reproduce error: https://github.com/8991hnim/Hilt-Multi-Modules-Sample The project has 3 modules: :app :feature (contains WillErrorFragment - which I'm trying to @AndroidEntryPoint on this fragment) :base (contains BaseFragment and BaseFragment2 - I tried both ways but none worked.)
Module's relation: :app implements :feature :feature implements :base
When run will get compile errors. Please take a look at the repository. Thank you.
@bcorso it's been 1 week. Please give me some updates. I'm stuck :(
@8991hnim it's likely that this is due to missing transitive dependencies in the classpath during compilation. Hilt has the aggregating task flag to fix these issues automatically. Can you try enabling the flag by adding the following in your application's build.gradle
file:
hilt {
enableAggregatingTask = true
}
Something else must be going on, looking at @8991hnim's repro app, the processor is crashing with the following trace:
Caused by: java.lang.IllegalArgumentException
at com.google.common.base.Preconditions.checkArgument(Preconditions.java:128)
at dagger.internal.codegen.validation.InjectBindingRegistryImpl.getOrFindMembersInjectionBinding(InjectBindingRegistryImpl.java:339)
at dagger.internal.codegen.validation.InjectBindingRegistryImpl.tryRegisterMembersInjectedType(InjectBindingRegistryImpl.java:297)
at dagger.internal.codegen.validation.InjectBindingRegistryImpl.getOrFindMembersInjectionBinding(InjectBindingRegistryImpl.java:344)
at dagger.internal.codegen.binding.BindingGraphFactory$Resolver.lookUpMembersInjectionBinding(BindingGraphFactory.java:474)
at dagger.internal.codegen.binding.BindingGraphFactory$Resolver.resolveMembersInjection(BindingGraphFactory.java:774)
at dagger.internal.codegen.binding.BindingGraphFactory$Resolver.access$1300(BindingGraphFactory.java:309)
at dagger.internal.codegen.binding.BindingGraphFactory.lambda$createLegacyBindingGraph$4(BindingGraphFactory.java:216)
at dagger.internal.codegen.binding.BindingGraphFactory.createLegacyBindingGraph(BindingGraphFactory.java:213)
at dagger.internal.codegen.binding.BindingGraphFactory.createLegacyBindingGraph(BindingGraphFactory.java:242)
at dagger.internal.codegen.binding.BindingGraphFactory.createLegacyBindingGraph(BindingGraphFactory.java:242)
at dagger.internal.codegen.binding.BindingGraphFactory.createLegacyBindingGraph(BindingGraphFactory.java:242)
at dagger.internal.codegen.binding.BindingGraphFactory.create(BindingGraphFactory.java:119)
at dagger.internal.codegen.ComponentProcessingStep.processRootComponent(ComponentProcessingStep.java:117)
at dagger.internal.codegen.ComponentProcessingStep.process(ComponentProcessingStep.java:95)
at dagger.internal.codegen.ComponentProcessingStep.process(ComponentProcessingStep.java:55)
at dagger.internal.codegen.validation.XTypeCheckingProcessingStep.lambda$process$0(XTypeCheckingProcessingStep.java:55)
at com.google.common.collect.RegularImmutableMap.forEach(RegularImmutableMap.java:185)
at dagger.internal.codegen.validation.XTypeCheckingProcessingStep.process(XTypeCheckingProcessingStep.java:52)
at dagger.internal.codegen.validation.XTypeCheckingProcessingStep.process(XTypeCheckingProcessingStep.java:39)
at dagger.shaded.androidx.room.compiler.processing.javac.JavacBasicAnnotationProcessor$DelegatingStep.process(JavacBasicAnnotationProcessor.kt:62)
at dagger.shaded.auto.common.BasicAnnotationProcessor.process(BasicAnnotationProcessor.java:228)
at dagger.shaded.auto.common.BasicAnnotationProcessor.process(BasicAnnotationProcessor.java:208)
at org.jetbrains.kotlin.kapt3.base.incremental.IncrementalProcessor.process(incrementalProcessors.kt:90)
at org.jetbrains.kotlin.kapt3.base.ProcessorWrapper.process(annotationProcessing.kt:175)
at jdk.compiler/com.sun.tools.javac.processing.JavacProcessingEnvironment.callProcessor(JavacProcessingEnvironment.java:980)
... 41 more
@8991hnim it's likely that this is due to missing transitive dependencies in the classpath during compilation. Hilt has the aggregating task flag to fix these issues automatically. Can you try enabling the flag by adding the following in your application's
build.gradle
file:hilt { enableAggregatingTask = true }
Thanks, it works 💯
@8991hnim it's likely that this is due to missing transitive dependencies in the classpath during compilation. Hilt has the aggregating task flag to fix these issues automatically. Can you try enabling the flag by adding the following in your application's
build.gradle
file:hilt { enableAggregatingTask = true }
Thanks, it works 💯
still its not working........
Please, solve the issue of injecting abstract class parameters : abstract class BaseFragment<VM : ViewModel, viewBinding : ViewDataBinding, repository : BaseRepository> : Fragment(){}
Everything was working fine when I was using dagger2 but having issues with using Hilt.
Hi Everybody, So I mentioned this yesterday on stackoverflow here i Have issues when try to use inject ViewModel to BaseFragment with by viewModels() extension so i used Factory to inject it when i do that my BaseFragment Have tow generic type and it show me that error
error: expected
topLevelClass = BaseFragment<T, D>.class
^error: [Hilt]
and the Generated Class is BaseFragment_GeneratedInjector :
so i try this workgound in this issues
and it show same error and new Error says :
``` [Hilt] Processing did not complete. See error above for details.error: [Hilt] @AndroidEntryPoint class expected to extend Hilt_ContactUsFragment. Found: BaseFragment**