For an ordinary (non-nested fragment) I use the following approach
1) create dependencies(...) method for setting fragment's dependencies
class MyFragment extends MyFragment {
void dependencies(Deps deps);
}
2) in MyFragment parent's activity onAttachFragment() method I just provide dependencies for fragment
class MyActivity{
void onAttachFragment(Fragment f){
((MyFragment)f).dependencies(deps);
}
}
For nested fragment there is no more onAttachFragment fragment called. Providing dependencies for fragment just for providing dependencies for nested fragment seems to be very cumbersome. So how could I provide dependencies for it?
Injecting a Fragment is just as simple as injecting an Activity . Define your subcomponent in the same way. Instead of injecting in onCreate() as is done for Activity types, inject Fragment s to in onAttach() . Unlike the modules defined for Activity s, you have a choice of where to install modules for Fragment s.
Two popular dependency injection frameworks are Spring and Google Guice. The usage of the Spring framework for dependency injection is described in Dependency Injection with the Spring Framework - Tutorial. Also Eclipse RCP is using dependency injection.
Constructor Injection.You pass the dependencies of a class to its constructor.
Dagger is a fully static, compile-time dependency injection framework for Java, Kotlin, and Android. It is an adaptation of an earlier version created by Square and now maintained by Google.
Just do it off the context which will be an activity. Create a getter for the dependencies on your activity. Fragments have access to the parent activity whether nested or not. Cast the context and then call the getter to get the dependencies in the nested activity.
If MyFragment
depends upon MyNestedFragment
, and MyNestedFragment
depends upon Deps
; it follows that MyFragment
also depends upon Deps
. Of course, no instance of MyNestedFragment
exists when Activity.onAttachFragment()
is called, so you will have to wait until after you have inflated the layout in MyFragment.onCreateView()
before supplying MyNestedFragment
with its dependencies.
public class MyActivity {
...
void onAttachFragment(Fragment f){
((MyFragment)f).dependencies(deps);
}
public static class MyFragment extends Fragment {
private Deps deps;
void dependencies(Deps deps) {
this.deps = deps;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
// <fragment> element in fragment_main layout has
// android:tag set to nested_fragment
((MyNestedFragment)getChildFragmentManager()
.findFragmentByTag("nested_fragment"))
.dependencies(this.deps);
return rootView;
}
}
public static class MyNestedFragment extends Fragment {
void dependencies(Deps deps) {
...
}
}
...
}
If all of this seems a bit messy, that's because Fragments are not POJOs you can just wire up in some arbitrary manner. Their lifecycles must be managed by nested FragmentManagers. If you create your fragments programmatically rather than using the <fragment> element, you will have a bit more control over their lifecycle at the cost of more complexity.
If you want to treat Android like an IoC container, then RoboGuice may be what you are looking for:
public class MyActivity extends roboguice.activity.RoboFragmentActivity {
...
@Override
protected void onCreate(Bundle savedInstanceState) {
// This only needs to be called once for the whole app, so it could
// be in the onCreate() method of a custom Application subclass
RoboGuice.setUseAnnotationDatabases(false);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public static class MyNestedFragment extends Fragment {
@Inject
private Deps deps;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// this isn't necessary if you extend RoboFragment
roboguice.RoboGuice.getInjector(activity).injectMembers(this);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
//This would not even be possible in the previous example
// because onCreateView() is called before dependencies()
// can be called.
deps.method();
View rootView = inflater.inflate(R.layout.fragment_nested, container, false);
return rootView;
}
}
}
@Singleton
public class Deps {
public void method() {
System.out.println("Deps.method()");
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With