android开发:Dagger2入门学习

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 15:59   1870   0

Dagger2是一款依赖注入框架,可以让我们不再去new对象,像Spring也是一款依赖注入框架。

有如下场景:程序员在A类中去new B(),然后调用B类的方法。如果有一天B类的构造函数改变了,需要添加俩个参数,那我们是不是也需要修改A类中的代码,然后改成new B(String name, String id)。如果是一个大型互联网项目,在几千个地方里都引用了B类,那你是不是得一个一个的去找然后修改????(黑人问号脸)????,要是这么干老板绝对让你连夜卷铺盖走人。当然显然这是不可能的。所以Dagger2正是解决了这种问题。使用它我们就不要new对象,通过依赖注入的方式把对象主动注入。

1.在 android studio引入Dagger2的依赖

 implementation"com.google.dagger:dagger:2.14.1"
 annotationProcessor"com.google.dagger:dagger-compiler:2.14.1"

2.创建实体类 ,在构造函数上添加@Inject注解

public class UserBean {

    @Inject
    public UserBean() {
    }

    @Override
    public String toString() {
        return "UserBean{}";
    }
}

3.在activity中声明实体类的属性,并添加上@Inject注解

public class MainActivity extends AppCompatActivity {
    @Inject
    UserBean bean;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.e("哈哈哈", bean.toString());

    }


}

按我们常规思想运行后应该直接会输出"UserBean{}"才对,但是运行会爆空异常,因为这时候我们的userBaen对象还没注入进来,就像你产品生产了,商店也有了,总得有个快递给你的产品运到店里吧?所以它需要通过一个注射器注射到我们的activity中。Component就出现了,它类似一个容器,用来管理我们的对象,包过对象的生命周期。我们添加如下一个接口:

@Component
public interface CommonComponent {
    void inject(MainActivity activity);
}

然后在Activity中添加如下代码:

DaggerCommonComponent.builder().build().inject(this);

当你创建好CommonComponent后编译系统会自动帮你生成以Dagger开头的DaggerCommonComponent。最后运行你会发现控制台输出了:"UserBean{}",CommonComponent 相当于一个注射器一样,把拥有@Inject注解的实体注入到相应的activity。

DaggerCommonComponent.builder().build().inject(this);这句代码相当于告诉Component 我需注入对象。

接下来问题来了:如果我们的实体类里面有些第三方的属性怎么办?

/**
 * @Author: david.lvfujiang
 * @Date: 2019/10/25
 * @Describe:
 */
public class UserBean {
  
    Activity activity;

    @Inject
    public UserBean(Activity activity) {
        this.activity = activity;
    }

    @Override
    public String toString() {
        return "UserBean{}";
    }
}

现在UserBean里面多了个Activity属性,它是第三方架包的类,构造函数是没有@Inject注解的,所以生成不了对象,我们也不能去改它的构造函数。所以Dagger2提供了Module,Module用来创建一些第三方的对象提供给Component,Component注入的时候会去Module找这些第三方对象。

/**
 * @Author: david.lvfujiang
 * @Date: 2019/10/25
 * @Describe:
 */
@dagger.Module
public class Module {
    Activity activity;

    public Module(Activity activity) {
        this.activity = activity;
    }

    @Provides
    public Activity getActivity() {
        return  activity;
    }


}

我们对activity和Component进行修改:

/**
 * @Author: david.lvfujiang
 * @Date: 2019/10/25
 * @Describe:
 */
@Component (modules = Module.class)
public interface CommonComponent {
    void inject(MainActivity activity);
}
public class MainActivity extends AppCompatActivity {
    @Inject
    UserBean bean;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        DaggerCommonComponent.builder().module(new Module(this)).build().inject(this);
        Log.e("哈哈哈", bean.toString());
        bean.activity.toString();
    }

    @Override
    public String toString() {
        Log.e("哈哈哈", "调用了activity");
        return "";
    }
}

1.@Component (modules = Module.class)

Component 和module进行绑定

2. DaggerCommonComponent.builder().module(new Module(this)).build().inject(this);

多加了module(new Module(this)),等于说实例化了module并把我们的当前对象传入Module

按我的理解是:Component 去注入我们的userBean对象的时候发现它有一个成员属性activity,这个属性是第三方架包的,它则会去Module中执行所有@Provides注解的方法然后返回对应的第三方对象。

再比如说我们还想给userBean添加一个 Date对象,只需要在Module中添加一个方法:

@Provides
public Date getDate() {
    return  new Date();
}

所以最后我们运行得到的结果:E/哈哈哈: UserBean{} E/哈哈哈: 调用了activity

证明了我们把this传入到userBean的成员变量中

分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP