dagger2从入门到放弃-概念

前言

dagger2貌似从两年前开始在各大android论坛刷屏,一堆Retrofit+RxJava+Dagger2项目如雨后春笋一样冒了出来。不过当时并没有赶这个潮流,主要是因为手头上项目已经较为庞大,而引入dagger2这种入门门槛比较高的库到项目里收益并不好估计,当然更明显的原因就是懒咯。

那现在为啥要用dagger2呢?因为新公司有一套插件框架,在插件中引入dagger2的成本相对小了不少,可以实验性的去尝试下,但是最终还是决定不在项目中引入dagger2,原因最后一篇文章会说到。

什么是dagger2

关于dagger2的来龙去脉网上的文章说的足够多了,也就不多说了,只提下我觉得重要的几点

  • 编译期的依赖注入框架
  • 使用代码生成而不用反射

以上两点决定了dagger2的注入只限于编译期可以确定的静态注入,像View,Activity这种运行时产生,且实例是由android框架创建出来的对象只能作为被注入的组件,而无法做为依赖注入到其他地方。当然有舍有得

  • dagger2拥有更强的运行时性能
  • 较为完善的编译期代码检查
  • 因为在编译期就生成了全部代码,所以调试也没什么问题,不过个人觉得生成的代码不够直观,调试起来还是很麻烦

依赖注入框架解决的问题

先说说我理解的依赖

依赖是指某个模块A要实现某个功能需要其他模块B。

最原始也最简单的的方式是在模块内new一个B的对象出来,这样会造成B的构造函数修改,需要修改A中的代码,两者耦合度非常高。

依赖注入

依赖注入是不在A中去创建 B的实例,而是让上层调用者注入一个B的对象,这样可以让模块A不再因为B的构造方法的修改而改变

注意一点,依赖注入只让A摆脱了和B的构造函数的耦合,至于A中对B的依赖基于一个实现还是一个接口,依赖注入是管不着的(依赖注入和面向接口编程都是为了模块间解耦但是没有直接的关系)

如果A依赖于一个接口,而这个接口的实现B又是从外部传入的,这样可以让A完全独立于B而存在,复用起来就更为简单

依赖注入带来的问题

所有的下层模块将创建依赖的任务都往上抛,那么必然会导致最上层的模块需要创建所有必须的依赖,而到依赖的传递过程也会多很多setter或者增加很多构造参数

//网上找的一个比较合适的例子
public class LoginActivity extends AppCompatActivity {

    LoginActivityPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        OkHttpClient okHttpClient = new OkHttpClient();
        RestAdapter.Builder builder = new RestAdapter.Builder();
        builder.setClient(new OkClient(okHttpClient));
        RestAdapter restAdapter = builder.build();
        ApiService apiService = restAdapter.create(ApiService.class);
        UserManager userManager = UserManager.getInstance(apiService);
        
        UserDataStore userDataStore = UserDataStore.getInstance(
                getSharedPreferences("prefs", MODE_PRIVATE)
        );

        //Activity只需要依赖LoginActivityPresenter
        //但因为使用了依赖注入,让下层模块相互解耦,导致activity需要承担所有依赖的创建任务
        //也就多了上面那么多代码
        presenter = new LoginActivityPresenter(this, userManager, userDataStore);
    }
}

依赖注入框架的意义

依赖注入框架的目的就在于承担了最上层创建依赖的职责,并且利用注解在合适的地方注入依赖,简化依赖的创建和传递的模板代码

public class LoginActivity extends AppCompatActivity {

    @Inject
    LoginActivityPresenter presenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        //Satisfy all dependencies requested by @Inject annotation
        getDependenciesGraph().inject(this);
    }
}

当然简化掉的代码没那么夸张,创建依赖的方法只不过是从activity中移到了依赖注入框架中,而依赖注入框架和业务代码之间是没有耦合的,可以按照一定的规则进行复用

dagger2的基本概念

dagger2从入门到放弃-概念_第1张图片
injection.jpg

依赖的提供方

dagger2中有两种提供依赖的方式

  • 使用@Inject注解构造器的类
    • 使用在自己可以修改源码的类中
  • 使用@Module注解包含提供依赖方法的类,使用@Provide方法主角提供依赖的方法
    • 用在提供没有修改源码权限的类的依赖

依赖的需求方

其实也可以分为两类

  • 正常的类,使用了@Inject注解了成员变量的类
    • 这里注入依赖需要自己触发
  • @Inject注解构造器的类
    • 这里@Inject注解的成员变量和构造器参数都会去框架中去找,这个过程是编译时自动完成的
    • 这些类既是依赖的需求方也是依赖的提供方

依赖注入器

使用@Component或者@SubComponent注解的接口或者抽象类

  • 描述可以提供哪些依赖
  • 描述可以注入到哪些依赖需求方
  • 管理依赖的生命周期

也许看完上面一堆你还是一头雾水,那么后面就通过代码循序渐进来熟悉dagger2吧

相关文章

dagger2从入门到放弃-概念
dagger2从入门到放弃-最基础的用法介绍
dagger2从入门到放弃-Component的继承体系、局部单例
dagger2从入门到放弃-ActivityMultibindings
dagger2从入门到放弃-dagger.android
dagger2从入门到放弃-其他用法
dagger2从入门到放弃-多模块项目下dagger的使用
dagger2从入门到放弃-为何放弃

你可能感兴趣的:(dagger2从入门到放弃-概念)