I understand that with Dagger 2 I cannot inject in a base class and expect it to carry over to the child class. But why can I not call inject inside of a child class unless I explicitly have an inject
method for that class?
I tried following the example in this article: Dagger 2: Even Sharper, Less Square . This solution should allow me to call inject in a subclass, but when I test it I get a NullPointerException
for all of my @Inject
targets.
public abstract class BaseFragment extends Fragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
injectComponent(MyApplication.getComponent());
}
protected abstract void injectComponent(AppComponent component);
}
public class MyFragment extends BaseFragment {
@Inject MyDependency mDependency;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mDependency.doSomething(); // NullPointerException
...
}
...
@Override
public void injectComponent(AppComponent component) {
component.inject(this);
}
}
Is there another way to inject into each subclass without creating an inject method for each an every class? Or is that the only way Dagger 2 will work? If that is the case, I will end up with an absurdly long Component
class. With an inject method for every Activity
, Fragment
or various other helper classes:
@Singleton @Component(modules = {AppModule.class})
public interface AppComponent {
void inject(MyClass clazz);
void inject(MyClass2 clazz);
...
void inject(MyClassN clazz);
}
I would much rather have to call component.inject()
in every class, than have to do that along with another inject
method.
Although similar, I do not believe my question is a duplicate Dagger 2 Activity Injection Not Working . That question asks why the injection was not working, to which the answer would be: because Dagger 2 has a strong type-association and you must declare an inject
method for each and every class. This question focuses more on a way around the boilerplate, while hopefully maintaining strong type-association.
I found a nifty little trick, used in the AsymmetricFingerprintDialog sample application, though I do not know if I fully understand how it works. The sample uses the first iteration of Dagger, but a quick test showed that it works with Dagger 2 as well.
For each Fragment
I added an empty constructor with an @Inject
annotation, then used an @Inject
annotation to get an instance of the Fragment
in my Activity
.
public class MainActivity extends AppCompatActivity {
@Inject MyFragment mFragment;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MyApplication.getComponent().inject(this);
getSupportFragmentManager().beginTransaction
.replace(R.id.fragment_container, mFragment).commit();
...
}
}
public class MyFragment extends Fragment {
@Inject MyDependency mDependency;
@Inject
public MyFragment() {}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mDependency.doSomething();
...
}
}
This allows me to call MyApplication.getComponent().inject(this)
only in each Activity
, and the dependencies will be injected to the Fragment
classes as well. In this way, I only need an inject
method for each Activity
, and not each Fragment
.
@Singleton @Component(modules = {AppModule.class})
public interface AppComponent {
void inject(MainActivity activity);
}
I am curious as to how this works though. From what I can see it has nothing to do with Dagger, instead it seems to use the @Inject
annotation for its intended purpose? Though I am new to Dagger as well as JSR-330, so I am unsure.
Edit: This method only works with setRetainInstanceState(true)
, or if you save and restore the instance yourself.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.