dagger: Hilt: compilation error for inherited Fragments

Compilation fails for the next code:

@AndroidEntryPoint
open class CreateNoteFragment: Fragment() {
	@Inject
	lateinit var someValA: SomeClassA
        ...
}
@AndroidEntryPoint
class EditNoteFragment: CreateNoteFragment() {
	@Inject
	lateinit var someValB: SomeClassB
        ...
}

Compilation error:

error: method does not override or implement a method from a supertype
  @Override

Method from the class where the error occurs:

public abstract class Hilt_EditNoteFragment extends CreateNoteFragment {
  ...
  @Override
  protected void inject() {
    if (!injected) {
      injected = true;
      ((EditNoteFragment_GeneratedInjector) generatedComponent()).injectEditNoteFragment(UnsafeCasts.<EditNoteFragment>unsafeCast(this));
    }
  }

Possible problem: Hilt_CreateNoteFragment is generated for CreateNoteFragment class Hilt_EditNoteFragment is generated for EditNoteFragment class Hilt_EditNoteFragment extends CreateNoteFragment that doesn’t have inject() method

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Comments: 17

Commits related to this issue

Most upvoted comments

@Zhelyazko, for deeper inheritance you can use the same workaround for each base class, i.e. both CreateNoteFragment and NoteFragment would use the long-form notation for @AndroidEntryPoint.

@AlekseyMiheev, I’ll be submitting a fix to avoid having to use the workaround (i.e. you should be able to use the short-form of the annotation everywhere). The workaround isn’t mentioned in the release notes/documentation because it was more of an oversight than something we intended.

I can close out this issue once that fix is submitted.

I think it’s smart if you can use

@AndroidEntryPoint
abstract class AbstractFragment : Fragment() {

}

and when you have

class TasksFragment : AbstractFragment()

You wouldn’t have to do

@AndroidEntryPoint
class TasksFragment : AbstractFragment()

We should be able to fix this internally. I’ll work on getting this fix out shortly, but in the meantime there’s the following workarounds.

Workaround

In the meantime, you should be able to work around this using the long-form notation for @AndroidEntryPoint on your base class, e.g.

@AndroidEntryPoint(Fragment.class)
public class CreateNoteFragment extends Hilt_CreateNoteFragment {...}

Edit: @CraZyLegenD’s suggestion of removing @AndroidEntryPoint from the base class will also work if you don’t need to instantiate CreateNoteFragment directly.

Details:

The issue is that when using the short-form notation for @AndroidEntryPoint, the class hierarchy isn’t quite right until after bytecode injection. The class hierarchy for the generated parent class should be:

“Hilt_EditNoteFragment > CreateNoteFragment > Hilt_CreateNoteFragment > Fragment”

But before the bytecode injection it’s actually:

“Hilt_EditNoteFragment > CreateNoteFragment > Fragment”

Thus, using the long-form notation for @AndroidEntryPoint on CreateNoteFragment avoids relying on bytecode injection so that your class hierarchy is correct at compile time.

@qrezet, it should be fixed in the latest release, 2.28.3.

I’m experiencing a similar issue but I make use of a BasFragment which takes a generic type T , none of the hacks work for me (T is meant to be a generated binding class)