Activity graphs and non-found dependency

2019-08-28 17:22发布

问题:

I'm starting using the dagger, like it pretty much, but now facing some difficulties. My scenario is as follows: there's an activity and a dependency for it. Dependency is injected to the activity, and requires a reference to that activity. Just like this:

public class MainActivity extends BaseActivity {        
    @Inject ScbeHelper scbeHelper;

    @Override
    protected void onCreate(Bundle savedInstanceState) {    
        super.onCreate(savedInstanceState);
        ...
    }
}

public class ScbeHelper {

    protected static final String TAG = "scbe_helper";  
    private BaseActivity activityContext;

    @Inject 
    public ScbeHelper(BaseActivity context) {       
        this.activityContext = context;
    }
}

I'm following dagger's example from the github for activity's graphs. So I've created a similar structure in my project. First, the BaseActivity class, from which MainActivity is inherited:

public abstract class BaseActivity extends Activity {
    private ObjectGraph activityGraph;
    @Override
    protected void onCreate(Bundle savedInstanceState) {    
        super.onCreate(savedInstanceState);

        protoApp application = (protoApp) getApplication();
        // Exception happens in next line, inside plus() method
        activityGraph = application.getApplicationGraph().plus(getModules().toArray());

        // Inject ourselves so subclasses will have dependencies fulfilled when this method returns.
        activityGraph.inject(this);

        ((protoApp)getApplication()).inject(this);
    }

    protected List<Object> getModules() {
        return Arrays.<Object>asList(new ActivityModule(this));
    }

    public void inject(Object object) {
        activityGraph.inject(object);
    }
}

And the module:

@Module(injects={MainActivity.class})
public class ActivityModule {
    private final BaseActivity activity;

    public ActivityModule(BaseActivity activity) {
        this.activity = activity;
    }

    @Provides @Singleton BaseActivity provideActivity() {
        return activity;        
    }   
}

Now, the problem: No injectable members on com.example.proto.BaseActivity. Do you want to add an injectable constructor? required by public com.example.proto.ScbeHelper(com.example.proto.BaseActivity)

In other words, provider method ActivityModule.provideActivity() doesn't really provide the instance of BaseActivity for some reason, though in my understanding it's set up correctly. Does anyone see an error in my setup? Am I missing something in dagger's logic?

Thanks in advance!

回答1:

I'm no Dagger expert, but you have 2 issues:

  • you have a cyclical dependency: you helper want to have the activity injected, your activity wants to have the helper injected. I don't think Dagger can resolve this
  • your activity tries to get injected twice, once with the activity-level graph, once with the application-level graph

Here's what I did to get it to work:

  • in ScbeHelper: remove the @Inject annotation
  • in BaseActivity: remove ((protoApp)getApplication()).inject(this);
  • in ActivityModule: remove your provideActivity method (it's not going to be used anymore), and add the following method:
@Provides @Singleton ScbeHelper provideScbeHelper() {
    return new ScbeHelper(activity);
}

What this does is it provides your ScbeHelper with the context it needs, but leaves only 1 annotation-driven injection so dagger can resolve it. Hope this helps.