Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to inject dependency to nested android fragment?

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?

like image 488
wilddev Avatar asked Oct 10 '15 21:10

wilddev


People also ask

How do you inject a fragment?

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.

Can you give few examples of dependency injection?

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.

What is constructor injection in Android?

Constructor Injection.You pass the dependencies of a class to its constructor.

What is Google dagger?

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.


2 Answers

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.

like image 107
FriendlyMikhail Avatar answered Oct 21 '22 07:10

FriendlyMikhail


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()");
    }
}
like image 23
robinj Avatar answered Oct 21 '22 09:10

robinj