Git Product home page Git Product logo

Comments (4)

Jearil avatar Jearil commented on April 28, 2024

A basic example:

@Module
public class BaseModule {
  private Context context;
  public BaseModule(Context context) { this.context = context; }

  @Provides
  @ApplicationScope
  public Context providesContext() { return context; }
}

@Module
public class ContextModule {
  private Context context;
  public ContextModule(Context context) { this.context = context; }

  @Provides
  @ActivityScope
  public Context providesLocalContext() { return context; }

@ApplicationScope
@Component(modules = BaseModule.class)
public interface BaseComponent {
  @ApplicationScope
  public Context appContext();
}

@Component(dependencies = BaseComponent.class, modules = ContextModule.class)
public interface ActivityComponent {
  @ActivityScope
  public Context activityContext();
}

The idea for this is that some objects will use an application level context (mainly singletons like Volley) while others might need just the local context (Some business logic class in a fragment). Ideally I'd just be able to specify which I'd like via:

@Inject
public SomePresenter(@ActivityScope Context context) { ... }

or

@Inject
public VolleyHelper(@ApplicationScope Context context) { ... }

from dagger.

cgruber avatar cgruber commented on April 28, 2024

Looking at your example, I think you're conflating two concepts - scope and qualification, and are doing so because Android is insane and uses the Context API for both application-level things and activity-level things.

I recommend you either supply @Qualifier annotations to disambiguate application context from activity context, since these are two different instances, and you want them to be two different bindings,

... or (my recommendation) just drop using Context as a type, and bind Application and Activity, since nearly every usage where you'd consume these will either need to know one from the other, or won't care and will behave correctly for any Context, and so you can feed those methods the appropriate context yourself.

Then you don't have a lot of @Foo Context things sprinkled around your code. You just have two types - Application and Activity - being consumed where appropriate, and being treated as a Context where relevant. It'll save you a world of hurt.

As to scope validation, I think your problem will likely go away if you use @Qualifier and @Scope correctly. Scope goes in one of three places:

When attached to the type of a component interface, that scope annotation represents a constraint such that all bindings reachable by that component (either via included modules, or implicitly via @Inject constructors must either be unscoped, or be of the same scope as the component. For instance the following means that FooActivity must be @ActivityScoped as must any objects owned by MyActivityComponent except where it gets them from a dependency (which is a different component, so a different constraint applies). Like this:

@ActivityScope
@Component(...) interface MyActivityComponent {
  FooActivity activity()
}

A scope annotation can also go on a @Provides method or on the type of an injectable object (an object with an @Inject constructor). Like so:

@ActivityScope
class MyFoo implements Foo {
  @Inject MyFoo(Bar bar) {...}
}

@Module class MyModule {
  @ActivityScope Bar bar(BarImpl impl) { return impl; }
}

This signals to dagger that these bindings in question are to be memoized in the component that was marked with @ActivityScope.

Scope in Dagger is far less automagical than in Guice or Spring. Lifetimes are determined by the lifetime of the component's instance - what you get from the component builder. @Scope annotations don't change that semantic very much, they merely are used as a signal to share an instance across a component, and are used to ensure that you don't declare something in one component that you meant to use in a component with a different lifetime.

from dagger.

cgruber avatar cgruber commented on April 28, 2024

All that said, we shouldn't have illegal state exceptions, we should have proper compiler errors. Can you please provide a stack-trace so we can figure out what check we're letting slip through?

from dagger.

cgruber avatar cgruber commented on April 28, 2024

We have had several updates since this but was filed - for now I'll close it. Feel free to re-open it if you can replicate the behavior with the latest snapshot.

from dagger.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.