如何将依赖注入嵌套的android片段?

时间:2015-10-10 21:05:35

标签: android android-fragments dependency-injection android-nested-fragment

对于普通(非嵌套片段),我使用以下方法

1)创建用于设置片段依赖性的依赖项(...)方法

class MyFragment extends MyFragment {
      void dependencies(Deps deps);
}

2)在MyFragment parent的活动onAttachFragment()方法中我只提供了片段的依赖

class MyActivity{
    void onAttachFragment(Fragment f){
        ((MyFragment)f).dependencies(deps);
    }
}

对于嵌套片段,不再有 onAttachFragment 片段被调用。 为嵌套片段提供片段的依赖性似乎非常麻烦。那我怎么能为它提供依赖呢?

4 个答案:

答案 0 :(得分:5)

只需将其作为活动的上下文。为您的活动依赖项创建一个getter。无论是否嵌套,片段都可以访问父活动。转换上下文,然后调用getter以获取嵌套活动中的依赖项。

答案 1 :(得分:2)

如果MyFragment取决于MyNestedFragment,则MyNestedFragment取决于Deps;因此MyFragment也取决于Deps。当然,调用MyNestedFragment时不存在Activity.onAttachFragment()的实例,因此您必须等到MyFragment.onCreateView()中的布局膨胀之后再提供MyNestedFragment的依赖关系

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) {
            ...
        }
    }

    ...
}

如果所有这些看起来有点混乱,那是因为片段不是POJO,你可以以任意方式连线。他们的生命周期必须由嵌套的FragmentManagers管理。如果您以编程方式创建片段而不是使用&lt; fragment&gt;元素,您将以更复杂的代价更多地控制其生命周期。

如果您想将Android视为IoC容器,那么RoboGuice可能就是您所寻找的:

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()");
    }
}

答案 2 :(得分:2)

您尝试在附加片段时设置依赖项。而不是这样,尝试在需要时从片段中获取依赖关系。有一个例子:

public class MyActivity extends Activity {

    public Deps getDepsForFragment(Fragment fragment) {
        if (fragment instanceof MyFragment) {
            return depsForMyFragment;
        } else if (fragment instanceof MyNestedFragment) {
            return depsForMyNestedFragment;
        } else {
            return null;
        }
    }
}

public class MyFragment extends Fragment {

    private Deps deps;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            MyActivtiy myActivity = (MyActivtiy) context;
            deps = myActivity.getDepsForFragment(this);
        } catch (ClassCastException e) {
            throw new ClassCastException("This fragment attached to an activity which can't provide the required dependencies.");
        }
    }
}

// this is the same as the MyFragment
public class MyNestedFragment extends Fragment {

    private Deps deps;

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        try {
            MyActivtiy myActivity = (MyActivtiy) context;
            deps = myActivity.getDepsForFragment(this);
        } catch (ClassCastException e) {
            throw new ClassCastException("This fragment attached to an activity which can't provide the required dependencies.");
        }
    }
}

当然,您可以为活动中的deps制作单独的方法(例如getDepsForMyFragmentgetDepsForMyNestedFragment)。

答案 3 :(得分:1)

只需保留层次结构逻辑,它应该是这样的:

class MyActivity{
    void onAttachFragment(Fragment f){
        ((MyFragment)f).dependencies(deps);
    }
}

class MyFragment extends MyFragment {
      void dependencies(Deps deps) {
          //TODO: do dependencies of my fragment before
          ((MyNestedFragment)childF).nestedDependencies(deps);
          //TODO: do dependencies of my fragment after
      }
}

class MyNestedFragment extends MyNestedFragment {
      void nestedDependencies(Deps deps);
}