美文网首页
Dagger2使用指南

Dagger2使用指南

作者: 孤独的根号十二 | 来源:发表于2019-02-12 15:41 被阅读13次

    什么是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使用指南

          本文链接:https://www.haomeiwen.com/subject/shcodqtx.html