“一盘沙拉”带你入门Dagger2(四)之 @Singleton

时间:2022-03-16 21:03:14

系列文章

“一盘沙拉”带你入门Dagger2(一)之HelloWorld

“一盘沙拉”带你入门Dagger2(二)之带参数怎么办

“一盘沙拉”带你入门Dagger2(三)之@Qualifier

“一盘沙拉”带你入门Dagger2(四)之 @Singleton

“一盘沙拉”带你入门Dagger2(五)之 @Scope

@Singleton可以方便地实现单例(全局单例)

我们在Salad类里面引入两个Orange的实例,查看他们的内存地址

public class Salad {

@Inject//桔子1
Orange orange1;

@Inject//桔子2
Orange orange2;

...
public Salad() {
...

Log.e("TAG", "orange1内存地址:"+orange1.toString());
Log.e("TAG", "orange2内存地址:"+orange2.toString());

}

...
}

打印log:发现两个对象是两个内存地址,说明目前Orange不是单例

E/TAG: orange1内存地址:com.demo.dagger2demo2.Orange@16e3e55f
E/TAG: orange2内存地址:com.demo.dagger2demo2.Orange@3565cbac

下面我们使用@Singleton让Orange类实现单例

  1. 在SaladModule里,在provideOrange方法前添加 @Singleton 即可

    @Module
    public class SaladModule {
    ...


    @Singleton // 单例,注意是在方法上添加,不是在类上面
    @Provides
    public Orange provideOrange(Knife knife) {
    return new Orange(knife);
    }

    ...

    }
  2. 在SaladComponent里,在接口上添加@Singleton 注释 即可

    @Singleton //注意是在接口上添加,注意位置
    @Component(modules = {SaladModule.class})//指明要在那些Module里寻找依赖
    public interface SaladComponent {
    ...
    //不是在这里添加@Singleton
    Orange provideOragne();

    void inject(Salad salad);

    }
  3. Salad类不变,还是引入了两个Orange对象,打印log,发现两个对象的内存地址是一样的,证明此时Orange是单例
E/TAG: orange1内存地址:com.demo.dagger2demo2.Orange@16e3e55f
E/TAG: orange2内存地址:com.demo.dagger2demo2.Orange@16e3e55f

总结:

一个简单地注解,方便地实现了单例。
这个@Singleton 是java提供给我们的注解,其实在Dagger2里面有一个注解@Scope也是用来实现单例的(这个说法不严谨)

java提供的@Singleton 只能实现全局单例,即只要在这个app里,无论在哪里,这个类都是单例,
而Dagger2提供的@Scope,能够让一个类在某个区域内实现单例,脱离这个区域他又不是单例了。

比如:Knife小刀,我们让Knife在注入到苹果、桔子时是单例(即苹果、桔子用的是同一把刀),Knife在注入Meat(肉)这个类里时,是另一把刀(很显然,切肉和切水果不能使用同一把刀),这是如果使用@Singleton 是不行的,他使得Knife在全局都是单例(即切水果和切肉都是用同一把刀),但是使用@Scope可以实现这个需求。

Scope就是区域、范围的意思,他会让Dagger2知道,在那些范围内使用的是一个依赖的同一个对象,而不仅仅是在全局指定单例模式

下一篇,说说@Scope