Dagger2使用指南

什么是Dagger2?

Dagger2是一个依赖注入框架,那么何为依赖注入呢?依赖注入是面向对象编程的一种设计模式,其目的是为了降低程序耦合,这个耦合就是类之间的依赖引起的。
很多人说Dagger是脱裤子放屁,实际上是他们对Dagger的作用产生了误解,Dagger的作用是管理对象之间的依赖关系,从而降低耦合,而不是为了构建一个对象,是否使用Dagger的一个标准是看两个类之间的关系是依赖关系,还是组合或者聚合的关系。
举个例子说明,一个类Person,另一个类Car,如果Person的某个方法比如说drive,需要引用Car,则称Person类依赖于 Car类

Public Person{

...
public void drive(){
  Car toyota=new Car("TOYOTA");
  toyota.挂档;
  toyota.踩油门;
  toyota.打方向;
}
}

这其中的依赖关系,就导致了Person对象需要负责对象toyota的创建,甚至是整个生命周期的管理,而这样显然会带来耦合度高,不易维护等缺点,比如说要让这个男孩驾驶一辆Audi,则还需要修改类Person的代码。所以我们通常从外部传入一个Car对象,这就是所谓的依赖注入

Public Person{
...
 Car toyota;
public Person(Car car){
toyota=car;
}

public void drive(){
  toyota.挂档;
  toyota.踩油门;
  toyota.打方向;
}
}

但是直接在构造方法里面传递对象又会造成一个问题,随着后续业务增加也许又需要传入Phone,Computer试想一下如果一个工程中有5个文件使用了Person那是不是要改5个文件。
所以有的时候我们会直接通过set方法来注入对象,这就需要我们每次使用时都要做null判断,因为你可能会忘记为它set值,有没有更优美的解决方法呢?Dagger2来了。
dagger2的github地址:
https://github.com/google/dagger

使用步骤

1.添加依赖

  implementation 'com.google.dagger:dagger:2.11'
annotationProcessor 'com.google.dagger:dagger-compiler:2.11'

People.java

public class People {

    public People () {
        System.out.println("a people created");
    }

    public  void print(){
        Log.d("sun"," i am people");
    }
}

2.创建Module
什么是Module,你可以把它想象成一个工厂,可以向外提供一些类的对象,类名用@Module标注,方法用@Provides标注,类名和方法名没有特别规范
MainModule .java

@Module
public class MainModule {

    @Provides
    People providesPerson() {
        return new People ();
    }
}

3.创建MainComponent
MainComponent.java

@Component(modules = {MainModule.class})
public interface MainComponent {

    void inject(MainActivity mainActivity);
}

4.重新Build项目
5.在MainActivity中将component 关联进去

public class MainActivity extends AppCompatActivity {
@Inject
People people;
    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        MainComponent mainComponent =DaggerMainComponent.builder().mainModule(new MainModule()).build();
        mainComponent.inject(this);
        people.print();
    }
}

假定一个场景,现在People的构造方法改变了,我们给它增加了一个name属性和一个context属性

public class People {
    Context context;
    String name;
    public People(Context context,String name) {
        System.out.println("a people created");
        this.name=name;
        this.context=context;
    }

    public void print(){
        Log.d("sun"," i am people"+name);
        Toast.makeText(context,"i am people"+name,Toast.LENGTH_LONG).show();
    }
}

相应的修改MainModule.java

@Module
public class MainModule {

    public MainModule() {
    }
    @Provides
    People providesPerson(Context context,String log){
        return new People(context,log);
    }
}

或者新建一个Moudle

@Module
public class SubMainModule {

    @Provides
    People providesPerson(Context context, String log){
        return new People(context,log);
    }
}

新建ContextComponent和ContextModule

@Module
public class ContextModule {
    Context context;

    public ContextModule(Context context) {
        this.context = context;
    }
    @Provides
    Context getContext(){
        return context;
    }
}

@Component(modules = {ContextModule.class})
public interface ContextComponent {
    Context getContext();
}

同理创建StringComponent和StringModule。

然后修改MainComponent ,添加Component之间的依赖

@Component(dependencies = {StringComponent.class,ContextComponent.class},modules = {MainModule.class})
public interface MainComponent {
    void inject(MainActivity mainActivity);

}

最后绑定Activity

StringComponent stringComponent=DaggerStringComponent.builder().stringModule(new StringModule("abc")).build();
ContextComponent contextComponent=DaggerContextComponent.builder().contextModule(new ContextModule(mainActivity)).build();
DaggerMainComponent.builder().mainModule(new MainModule()).stringComponent(stringComponent).contextComponent(contextComponent).build().inject(mainActivity);

@Qualifier

如果一个Moudle提供了多种创建对象的方式,可以通过自定义标签的方式指定使用哪种方式

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface PeopleWithContext {
}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface PeopleWithName {
}

在Moudler中分别注解提供对象的方法

  // ...
    @PersonWithContext
    @Provides
    public Person providesPersonWithContext(Context context) {
        return new Person(context);
    }

    @PersonWithName
    @Provides
    public Person providesPersonWithName() {
        return new Person("yxm");
    }

在依赖注入的地方也使用标签注解

  @PersonWithContext
    @Inject
    Person p1;

    @PersonWithContext
    @Inject
    Person p2;

@Scope

@Scope可用于修饰自定义的注解,用@Scope修饰的注解来修饰
Moudle里面提供对象的方法会产生单例效果,但是注意必须给相应的Component提供注解,而且如果Moudle里面有多个提供对象的方法,那么每一个方法都会产生一个对象,实际上不是单例,@Singleton就是用@Scope修饰的注解

@Scope
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface ActivityScope {
}
    @ActivityScope
    @Provides
    Person providesPeople {
        return new Person();
    }
@ActivityScope
@Component(modules = {ActivityModule.class})
public interface ActivityComponent {
    void inject(MainActivity mainActivity);
}

总结:

Dagger说白了给我们提供了灵活创建对象的方式,对象的创建是在一层一层的依赖中实现的,例如前面的例子,修改构造函数时,只需要修改相应的Moudle,并且在当前Moudle中提供创建对象的元素,或者重新创建新的Moudle和Component,然后添加Component依赖,然后修改绑定的元素的代码,乍一看,这岂不是更复杂,实际上,有一些被依赖的Component对象并不是在需要使用时就创建的,而是提前创建或者封装在一些工具类中,从而简化我们的代码

你可能感兴趣的:(Dagger2使用指南)