question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

DI on generic class where a superclasses generic type is a generated class

See original GitHub issue

I’m currently building an app with Dagger 2 and Android DataBinding. I have a generic Activity base class in which the generic type specifies what ViewDataBinding subclass any child activities use for their UI.

public abstract class BaseActivity<T extends ViewDataBinding> extends AppCompatActivity {
    @Inject
    protected EventBus mEventBus;
    @Inject
    protected T mBinding;

    ...
}

public class MainActivity extends BaseActivity<ActivityMainBinding> {
    ...
}

Whenever I attempt to build my project the compilation fails and Dagger 2 gives no indication as to what the underlying issue is. After a lot of trial and error I could only find one answer; it seems as though Dagger 2 doesn’t like having a Component that injects into a generic class whose generic type is a generated class (i.e. ActivityMainBinding in the above example). If I remove the generic type from even MainActivity (i.e. make it default to using ViewDataBinding) it builds and runs as expected.

Is there any solution to this?

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:9

github_iconTop GitHub Comments

3reactions
fullkomnuncommented, Jan 24, 2017

I encountered this issue when using an abstract generic base class with a single type parameter that is bound to extend ViewDataBinding. When extending this base class and defining the concrete generated data binding class and trying to inject into the subclass (when the base class has any kind of injections) dagger fails to generate the MembersInjector for the base class since it cannot find the symbol for the generated data binding class. build config: dagger 2.8, android-gradle-plugin 2.2.3, gradle 3.2.1, build-tools 25.0.2. Also tried to use the latest android-gradle-plugin(2.3.0-beta2) and gradle(3.3). Tried to use android gradle plugin’s annotation processing support available since version 2.2.0 and the good old android-apt plugin.

public abstract class BindableBaseController<B extends ViewDataBinding> extends BaseController {
  @Inject void setupLeakCanary(LeakCanaryProxy leakCanaryProxy) {
    addLifecycleListener(new LeakCanaryControllerLifecycleListener(leakCanaryProxy));
  }
  ...
}

public final class LoginController extends BindableBaseController<LoginControllerBinding> {
  @Override protected void injectDependencies() {
    ComponentFinder.<LoginActivityComponent>findActivityComponent(getActivity()).plus(
        new LoginControllerModule()).inject(this);
  }
  ...
}

the error: “Note: Generating a MembersInjector for ***.login.LoginController. Prefer to run the dagger processor over that class instead. Error:(23, 46) error: cannot find symbol class LoginControllerBinding where B is a type-variable: B extends ViewDataBinding declared in class BindableBaseController_MembersInjector”

the generated members injector:

@Generated(
  value = "dagger.internal.codegen.ComponentProcessor",
  comments = "https://google.github.io/dagger"
)
public final class BindableBaseController_MembersInjector<B extends ViewDataBinding>
    implements MembersInjector<BindableBaseController<LoginControllerBinding>> {
  private final Provider<LeakCanaryProxy> leakCanaryProxyProvider;

  public BindableBaseController_MembersInjector(Provider<LeakCanaryProxy> leakCanaryProxyProvider) {
    assert leakCanaryProxyProvider != null;
    this.leakCanaryProxyProvider = leakCanaryProxyProvider;
  }

  public static <B extends ViewDataBinding>
      MembersInjector<BindableBaseController<LoginControllerBinding>> create(
          Provider<LeakCanaryProxy> leakCanaryProxyProvider) {
    return new BindableBaseController_MembersInjector<B>(leakCanaryProxyProvider);
  }

  @Override
  public void injectMembers(BindableBaseController<LoginControllerBinding> instance) {
    if (instance == null) {
      throw new NullPointerException("Cannot inject members into a null reference");
    }
    ((BaseController) instance).setupLeakCanary(leakCanaryProxyProvider.get());
  }
}

Is there any way to make sure the generated data binding class is generated and available to use by dagger’s generated code?

0reactions
krakowskicommented, Apr 16, 2017

Sure, opened #698 just now. Thanks.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Generic Classes - C# Programming Guide - Microsoft Learn
Generic classes encapsulate operations that are not specific to a particular data type. The most common use for generic classes is with ...
Read more >
C# generics: does compiler creates only one specialized ...
Each usage of the generic type with a different type parameter generates a different new reified type for that parameter. However, it is...
Read more >
Generics: in, out, where | Kotlin
The general rule is this: when a type parameter T of a class C is declared out , it may occur only in...
Read more >
typing — Support for type hints — Python 3.11.1 documentation
This module defines several types that are subclasses of pre-existing standard library classes which also extend Generic to support type variables inside [] ......
Read more >
Programming With Java Generics - Angelika Langer
How do I generify an existing non-generic type or method? ... is provided by means of a Class object when the checked view...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found