Dagger2使用详解

Dagger2简介

Dagger2是Dagger的升级版,是一个依赖注入框架,第一代由大名鼎鼎的Square公司共享出来,第二代则是由谷歌接手后推出的,现在由Google接手维护。

Githu:https://github.com/google/dagger

依赖注入

依赖注入是面向对象编程的一种设计原则,其目的是为了降低程序耦合,这个耦合就是类之间的依赖引起的。

举个栗子:

public class ClassA {
    private ClassB b

    public ClassA(ClassB b) {
        this.b = b;
    }
}

这里ClassA的构造函数里传了一个参数ClassB,随着后续业务增加也许又需要传入ClassCClassD。试想一下如果一个工程中有5个文件使用了ClassA那是不是要改5个文件?

这既不符合开闭原则,也不符合单一职责原则,这个时候大杀器Dagger2就该出场了:

public class ClassA {
    @inject 
    private ClassB b;

    public ClassA() {
    }
}

通过注解的方式将ClassB b注入到ClassA中,可以灵活配置ClassA的属性而不影响其他文件对ClassA的使用。

简单的说,就是一个工厂模式,由Dagger负责创建工厂,帮忙生产instance。遵从Java规范JSR 330,可以使用这些注解。现在不研究Dagger2是如何根据注解去生成工厂的,理解为什么可以实现DI(Dependency Injection),如何创建IoC(Inverse of Control)容器。

Dagger2依赖注入

Dagger2使用

在实际项目中Dagger2一般和MVP模式配合使用

引入Dagger2

api 'com.google.dagger:dagger:2.28.3'
annotationProcessor 'com.google.dagger:dagger-compiler:2.28.3'

定义IView

//IView类
public interface ICommonView {
    Context getContext();
}

定义Module

创建一个类CommonModule

@Module
public class CommonModule {
    private ICommonView iView;

    public CommonModule(ICommonView iView) {
        this.iView = iView;
    }

    @Provides
    public ICommonView provideIcommonView() {
        return this.iView;
    }
}

定义Component

创建一个接口CommonComponent

@Component (modules = CommonModule.class)
public interface CommonComponent {
    void inject(LoginActivity activity); 
}

定义Presenter

build一下项目,然后在LoginPresenter里使用@Inject@Inject来自javax包,不是Dagger2自定义的)

public class LoginPresenter {
    ICommonView iView;

    @Inject
    public LoginPresenter(ICommonView iView) {
        this.iView = iView;
    }

    public void login(User user) {
        Context mContext = iView.getContext();
        Toast.makeText(mContext, "login......", Toast.LENGTH_SHORT).show();
    }
}

使用CommonComponent接口

LoginActivity中使用CommonComponent接口

public class LoginActivity extends AppCompatActivity implements ICommonView {
    @BindView(R.id.btn_login)
    Button btn;
    @Inject
    LoginPresenter presenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        ButterKnife.bind(this);
        DaggerCommonCompnent
                .builder()
                .commonModule(new CommonModule(this))
                .build()
                .inject(this);
    }

    @OnClick(R.id.btn_login)
    void login() {
        presenter.login(new User());
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    public Context getContext() {
        return this;
    }
}

解耦

有没有注意到loginPresenter并没有初始化?这个简单Demo要展示的重点就是loginPresenterLoinActivity彻底解藕,后续无论怎样修改loginPresenter的构造方法都不需要改动LoinActivity的代码。如果loginPresenter构造函数增加参数要改谁的代码呢?当然是CommonModudle了,其实也很简单,例如增加了一个新参数ImyView就在CommonModudle.java中新增一个方法

@Provides
public ImyView provideMyView() {
    return myView; // myView是ImyView的实例
}

注意别漏了@Provides,它是Dagger2自定义的注解,也是通过它Dagger2才能正常把新增的参数传入loginPresenter构造器。

命名规约

  • @Provides方法用provide前缀命名
  • @ModuleModule后缀命名
  • @ComponentComponent作为后缀

Dagger2总结

Dagger2是通过依赖注入完成类的初始化,这个过程需要三部分:

  • 依赖提供方(生产者)
  • 依赖注入容器(桥梁)
  • 依赖需求方(消费者)

Dagger2是怎么选择依赖提供的呢,规则是这样的:

步骤1:查找Module中是否存在创建该类的方法
步骤2:若存在创建类方法,查看该方法是否存在参数
步骤2.1:若存在参数,则按从步骤1开始依次初始化每个参数
步骤2.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束
步骤3:若不存在创建类方法,则查找Inject注解的构造函数,看构造函数是否存在参数
步骤3.1:若存在参数,则从步骤1开始依次初始化每个参数
步骤3.2:若不存在参数,则直接初始化该类实例,一次依赖注入到此结束

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/03/29/dagger2-usage-details/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
Dagger2使用详解
Dagger2简介 Dagger2是Dagger的升级版,是一个依赖注入框架,第一代由大名鼎鼎的Square公司共享出来,第二代则是由谷歌接手后推出的,现在由Google接手维护。 ……
<<上一篇
下一篇>>
文章目录
关闭
目 录