Android 片段和依赖注入

Posted

技术标签:

【中文标题】Android 片段和依赖注入【英文标题】:Android Fragment and Dependency Injection 【发布时间】:2014-06-16 01:15:19 【问题描述】:

正如标题所说,我试图找出哪一个是在片段中注入依赖项的最佳方法。 我想独立于 RoboGuice 等外部框架。

现在,以最简单的方式,我有一个抽象某种逻辑的接口,并且我想从一个 Activity 中注入这个接口的实现。我知道我必须为我的片段提供一个默认构造函数,因为系统可能需要在某些时候重新创建片段,并且创建片段的新实例的常用方法是提供处理创建的静态方法,例如这个:

public static Fragment newInstance() 
    final Bundle bundle = new Bundle();
    ...
    final Fragment fragment = new MyFragment();
    fragment.setArguments(bundle);
    return fragment;

如何将我的依赖项传递给片段?我应该让它实现 Parcelable 或 Serializable 接口,然后将其打包到 Bundle 中吗?有没有其他方法可以达到效果?

【问题讨论】:

【参考方案1】:

一个简单的解决方案是声明一个接口,该接口声明片段所需的依赖项。然后让Fragment的Context实现这个接口,在需要的时候从Context中轮询依赖。

合同:

public interface MyDependencies 

    MyDep getDep();


活动:

public MyActivity extends Activity implements MyDependencies 

    @Override
    public MyDep getDep()
       return createMyDependencyOrGetItFromASingletonOrGetItFromApplication()
    

片段:

public void onActivityCreated(Bundle b)
     super.onActivityCreated(b)

     if (getActivity() instanceOf MyDependencies) 
         MyDep dep = ((MyDependencies) getActivity).getDep();
      else 
         throw new RuntimeException("Context does not support the Fragment, implement MyDependencies")
     

因此,事实上,由于契约是由接口定义的,因此与 Activity 没有不必要的耦合。

【讨论】:

喜欢那个方法名“createMyDependencyOrGetItFromASingletonOrGetItFromApplication”lol【参考方案2】:

你为什么不从你的活动中获取依赖?

public void onActivityCreated( Bundle b)
     super.onActivityCreated(b)
     DependencyClass c = ((MyActivity)getActivity()).getDependency();

【讨论】:

如果我这样做,我最终会将 Fragment 耦合到 Activity 对吗?我仍然希望 Fragment 是独立且可重用的。【参考方案3】:

如果你不能通过构造函数传入依赖(如果你需要一个默认构造函数),并且你不想使用像 Dagger 或 RoboGuice 这样的依赖注入库,另一种经典的方法是使用 setter “注入”依赖项。

Fragment MyFragment 

Depend mDepend;

....


    public void setDepend(Depend depend) 
        mDepend = depend;
    


然后在您的活动中,您可以在 onCreate 方法中注入依赖项。

所以在你的活动中是这样的:

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_map);
    MapFragment wrapperFragment = new WrapperFragment();
    if (savedInstanceState == null) 
        getFragmentManager().beginTransaction()
                .add(R.id.map_container, wrapperFragment).commit();
    // find the fragment
    // call the setter
    

【讨论】:

这个解决方案的问题是,当android重新创建片段时,它使用默认构造函数并且不调用set方法,即使它们之前已经调用过。

以上是关于Android 片段和依赖注入的主要内容,如果未能解决你的问题,请参考以下文章

Android Dagger片段可以访问AppModule和ActivityModule依赖关系,但不能访问FragmentModule依赖关系

IOC 控制反转Android 视图依赖注入 ( 视图依赖注入步骤 | 视图依赖注入代码示例 )

IOC 控制反转Android 布局依赖注入 ( 布局依赖注入步骤 | 布局依赖注入代码示例 )

Android依赖注入Dagger的使用和源码解析(上篇)

IOC 控制反转Android 事件依赖注入 ( 事件依赖注入代码示例 )

在 Android 中通过 Hilt 进行依赖项注入