dagger2 的安卓支持库的使用

将以下内容添加到build.gradle中(未包括dagger2基本依赖)

dependencies {
  compile 'com.google.dagger:dagger-android:2.x'
  compile 'com.google.dagger:dagger-android-support:2.x' // if you use the support libraries
  annotationProcessor 'com.google.dagger:dagger-android-processor:2.x'
}

为什么要使用dagger2的安卓支持库

很多Android框架类,比如Activity和Fragment,由系统本身实例化,如果dagger可以创造所有注入对象,它可以工作得最好。相反的,如果你不得不在生命周期的方法中执行注入对象注入,这样意味着有些类会看起来像这样。

public class FrombulationActivity extends Activity {
  @Inject Frombulator frombulator;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // DO THIS FIRST. Otherwise frombulator might be null!
    ((SomeApplicationBaseType) getContext().getApplicationContext())
        .getApplicationComponent()
        .newActivityComponentBuilder()
        .activity(this)
        .build()
        .inject(this);
    // ... now you can write the exciting code
  }
}

这样做有几个问题
1.复制粘贴代码会使重构变得困难,当越来越多的开发者复制粘贴那段代码,很少有人知道它实际做了什么。
2.更根本的是,它需要请求注入(FrombulationActivity)的类型来了解其注入器。即使这是通过接口而不是具体类型完成的,它打破了依赖注入的核心原则:类不应该知道注入的方式。
所以dagger2开发者弄出了这么一套框架。
怎么实现呢?
1.安装AndroidInjiectionModule在应用程序中以确保这些基本类型所需的所有绑定都可用。(就是引入依赖)
2.首先写一个SubComponent接口扩展AndroidInjector,该接口有继承了AndroidInjector.Builder的方法(注意注释)

@Subcomponent(modules = ...)
public interface YourActivitySubcomponent extends AndroidInjector {
  @Subcomponent.Builder
  public abstract class Builder extends AndroidInjector.Builder {}
}

3.在定义完Subcomponent后,添加它到你的component分层结构中,具体做法是定义一个绑定了subcomponent builder的module,再将该module添加到注入你Applicationa的component中。

@Module(subcomponents = YourActivitySubcomponent.class)
abstract class YourActivityModule {
  @Binds
  @IntoMap
  @ActivityKey(YourActivity.class)
  abstract AndroidInjector.Factory
      bindYourActivityInjectorFactory(YourActivitySubcomponent.Builder builder);
}

@Component(modules = {..., YourActivityModule.class})
interface YourApplicationComponent {}

Pro-tip:如果你的Subcomponent和它的builder没有其他方法或者supertypes,你可以使用ContributesAndroidInjector去自动生成上面两个步骤中的代码。添加一个抽象module并返回你的activity,并用@ContributesAndroidInjector,然后声明你想要安装到subcomponent中的modules,如果这个subcomponent需要scopes,在该方法中声明注释。

@ActivityScope
@ContributesAndroidInjector(modules = { /* modules to install into the subcomponent */ })
abstract YourActivity contributeYourActivityInjector();

4.让你的Application实现HasActivityInjector并且@Inject一个DispatchingAndroidInjector并且从activityInjector方法中返回

public class YourApplication extends Application implements HasActivityInjector {
  @Inject DispatchingAndroidInjector dispatchingActivityInjector;

  @Override
  public void onCreate() {
    super.onCreate();
    DaggerYourApplicationComponent.create()
        .inject(this);
  }

  @Override
  public AndroidInjector activityInjector() {
    return dispatchingActivityInjector;
  }
}

5.在你的Activity.onCreate()方法中在调用super.onCreate()方法前调用AndroidInjection.inject(this)方法

public class YourActivity extends Activity {
  public void onCreate(Bundle savedInstanceState) {
    AndroidInjection.inject(this);
    super.onCreate(savedInstanceState);
  }
}

6.完成

那么它是怎么工作的呢?

AndroidInjection.inject()得到了来自Application的DispatchingAndroidInjector并将您的activity传递给inject(Activity)。DispatchingAndroidInjector查找AndroidInjector.Factory作为您的activity的类(这是YourActivitySubcomponent.Builder),创建了 AndroidInjector(这是YourActivitySubcomponent),并传递你的activity给inject(YourActivity)。

注入Fragment对象
注入一个Fragment和注入一个Activity一样简单。用同样的方法定义你的subcomponent,用Fragment.@FragmentKey和HasFragmentInjector
类型代替Activity.@ActivityKey和HasActivityInjector
用在onAttach()注入Fragments代替在onCreate()中的注入。
和在Activitys中定义modules不同,你有在何时为Fragments安装modules的选择。你可以让你的Fragment 成为另一个Fragment component,一个Activity component或者Application component的subcomponent。它取决于你的Fragment需要绑定哪个。在决定component位置后,让相应的类型(Activity)实现HasFragmentInjector。比分说,如果你的Fragment需要绑定YourActivitySubcomponent,你的代码会像这个样子:

public class YourActivity extends Activity
    implements HasFragmentInjector {
  @Inject DispatchingAndroidInjector fragmentInjector;

  @Override
  public void onCreate(Bundle savedInstanceState) {
    AndroidInjection.inject(this);
    super.onCreate(savedInstanceState);
    // ...
  }

  @Override
  public AndroidInjector fragmentInjector() {
    return fragmentInjector;
  }
}

public class YourFragment extends Fragment {
  @Inject SomeDependency someDep;

  @Override
  public void onAttach(Activity activity) {
    AndroidInjection.inject(this);
    super.onAttach(activity);
    // ...
  }
}

@Subcomponent(modules = ...)
public interface YourFragmentSubcomponent extends AndroidInjector {
  @Subcomponent.Builder
  public abstract class Builder extends AndroidInjector.Builder {}
}

@Module(subcomponents = YourFragmentSubcomponent.class)
abstract class YourFragmentModule {
  @Binds
  @IntoMap
  @FragmentKey(YourFragment.class)
  abstract AndroidInjector.Factory
      bindYourFragmentInjectorFactory(YourFragmentSubcomponent.Builder builder);
}

@Subcomponent(modules = { YourFragmentModule.class, ... }
public interface YourActivityOrYourApplicationComponent { ... }

基本框架类型
Dagger2提供了DaggerActivity DaggerFragment 和 DaggerApplication这些基本框架类型,实现了HasActivityInjector/HasFragment以及调用AndroidInjection.inject().
以下类型也包括在内:

  • DaggerServiceDaggerIntentService
  • DaggerBroadcastReceiver
  • DaggerContentProvider

注意: DaggerBroadcastReceiver只能在 BroadcastReceiver注册时使用AndroidManifest.xml。当 BroadcastReceiver在你自己的代码中创建时,更喜欢构造器注入。

支持库

对于Android支持库的用户,dagger.android.support包中存在并行类型 。请注意,尽管支持Fragment用户必须绑定AndroidInjector.Factory,但AppCompat用户应继续执行,AndroidInjector.Factory而不是(或FragmentActivity)。

何时注射

只要有可能,构造方法注入是首选,因为它javac确保在设置之前没有引用字段,这有助于避免NullPointerExceptions。当需要成员注射(如上所述)时,倾向于尽早注射。为此,DaggerActivity 呼吁AndroidInjection.inject()立即onCreate(),调用之前 super.onCreate()DaggerFragment做同样的onAttach(),这也防止了矛盾,如果Fragment重新连接。

AndroidInjection.inject()在之前调用是非常重要super.onCreate()Activity,因为调用在配置更改期间从先前的活动实例中super附加Fragments,而这又会注入 Fragments。为了使Fragment注射成功,Activity 必须已经注射。对于ErrorProne的用户来说,调用AndroidInjection.inject()之后会出现编译器错误super.onCreate()

以上内容来自dagger2官网中的详解介绍。
更具体的参考了google的官方demo后,有了这么几个小结。
1.让Activity、Fragment和Application继承Dagger2提供的基本类型可以省去步骤4和5
2.由于Activity和Fragment在实现注入的时候,子组件及其构建器没有其他方法或supertypes,因此都可以使用Pro-tips中的方法自动生成代码。
3.在定制的Application中重写了applicationInjector()方法,该方法告诉Dagger如何制造我们的@Singleton Component。
4.为了进一步解耦,activity之间传值的时候,传值activity不用改,接收值的方法在接收activity的module中声明。Activity中接收值的变量需要用@Inject注释。

你可能感兴趣的:(dagger2 的安卓支持库的使用)