Dagger 2从浅到深(五)

来源:互联网 发布:python模块化编程实例 编辑:程序博客网 时间:2024/06/04 23:29

Dagger系列:

  1. Dagger 2从浅到深(一)
  2. Dagger 2从浅到深(二)
  3. Dagger 2从浅到深(三)
  4. Dagger 2从浅到深(四)
  5. Dagger 2从浅到深(五)
  6. Dagger 2从浅到深(六)
  7. Dagger 2从浅到深(七)
  8. Dagger 2应用于Android的完美扩展库-dagger.android

总所周知的是,Android的内存是十分昂贵的,所以,能省就省。这也造成了,有时候想延迟实例化对象,在需要的时候,才会进行实例化。就像冰箱里的水果一样,等我想吃的时候,才会拿出来,保证它的新鲜度。

又有时候,注入的是实例的列表,而不是单个实例的值。如果列表少,还可以重复调用@Inject注入实例。如果列表说在几十甚至上百时,也重复调用@Inject么?感觉有点繁琐哦。

Lay<T>和Provider<T>,不由自主的进入的我们的视线,它又给我们带来什么样的惊喜呢!!!

Lazy<T>

对于任何绑定的对象T,当你想惰性实例化它时,都可以创建一个延迟实例化的Lazy<T>。当你需要它时,调用get()方法时,就会实例化对象。

public class BananaBean {    @Inject    public BananaBean() {        Log.d("test", "BananaBean()");    }}public class FruitActivity extends AppCompatActivity {    ***    @Inject    Lazy<BananaBean> mBananaBeanLazy;    @Override    protected void onCreate(Bundle savedInstanceState) {        ***        BananaBean beanA = mBananaBeanLazy.get();        //  advanced.todo.com.daggerlearn.bean.BananaBean@3d061bc6        Log.d("test", beanA.toString());        BananaBean beanB = mBananaBeanLazy.get();        //  advanced.todo.com.daggerlearn.bean.BananaBean@3d061bc6        Log.d("test", beanB.toString());    }    ***}

现惰性注入了BananaBean的两个实例 - beanA和beanB,看它们的内存地址是一样的。另一方面,BananaBean的构造函数只有在创建beanA,也就是第一次调用get()方法时调用了一次。也就是说,Lazy只有第一次调用get()方法时,调用构造函数实例化对象,然后将该对象缓存。以后再调用get()方法时,都会返回缓存的实例,并且不会再调用构造函数,创建实例。

这里写图片描述


注意:

  1. 如果T是单例,那么Lazy<T>将是ObjectGraph内所有注入的实例;否则,每个注入点将创建自己的Lazy<T>实例。
  2. 无论如何,对任何给定的Lazy<T>实例的调用将返回相同的底层实例.

Provider<T>

有时您需要注入多个实例列表,而不是仅注入单个值。此时,有多种选择,比如工厂模式、Builder模式等。当然,你还有另外一种选择,那就是选择注入一个Provider <T>,而不只是T。

当Provider<T> 每次调用get()方法时,都会执行绑定逻辑并创建一个实例。

现有类BananaBean,其构造函数被@Inject注解。在FruitActivity类中,注入了Provider实例,然后调用其get()方法,创建BananaBean实例。

public class BananaBean {    @Inject    public BananaBean() {        Log.d("test", "BananaBean()");    }}public class FruitActivity extends AppCompatActivity {    ***    @Inject    Provider<BananaBean> mBananaBeanProvider;    @Override    protected void onCreate(Bundle savedInstanceState) {        ***        BananaBean beanA = mBananaBeanProvider.get();        BananaBean beanB = mBananaBeanProvider.get();        // advanced.todo.com.daggerlearn.bean.BananaBean@3d061bc6        Log.d("test", beanA.toString());        // advanced.todo.com.daggerlearn.bean.BananaBean@3d061bc6        Log.d("test", beanB.toString());    }    ***}

从Log打印中,我们可以清晰看出来,每次调用get()方法,都会调用BananaBean的构造函数,实例化一个新的对象,而不像Lazy<T>那样将第一次创建的实例缓存。

这里写图片描述

这时,会有一个疑问,我们所知道的是,BananaBean被@Scope注解时,在Scope作用范围内,只有第一次注入时,调用构建函数,创建一个新的实例对象,然后将该对象缓存,后续的注入实例都是调用该缓存。Provder<T>中的T,被Scope注解时,会怎么样呢?下面,我们修改下BananaBean类,用@TodoScope注解它,但是FruitActivity不做任何修改。我们看mBananaBeanProvider调用get()方法时的效果:

@TodoScopepublic class BananaBean {    @Inject    public BananaBean() {        Log.d("test", "BananaBean()");    }}public class FruitActivity extends AppCompatActivity {    ***    @Inject    Provider<BananaBean> mBananaBeanProvider;    @Override    protected void onCreate(Bundle savedInstanceState) {        ***        BananaBean beanA = mBananaBeanProvider.get();        BananaBean beanB = mBananaBeanProvider.get();        // advanced.todo.com.daggerlearn.bean.BananaBean@3d061bc6        Log.d("test", beanA.toString());        // advanced.todo.com.daggerlearn.bean.BananaBean@3d061bc6        Log.d("test", beanB.toString());    }    ***}

此时,在两次调用mBananaBeanProvider的get()方法时:

  • BananaBean的构造函数被调用了一次
  • beanA和beanB的内存一致

我们可以这么认为,尽管是Provider<T>提供注入的对象,但@Scope注解的功能依然存在。

这里写图片描述

其中,官方对Provider<T>的解释是:Provider<T>将通过get()方法提供T实例,通常是由注入器来实现。从Dagger 2从浅到深(四),我们已经了解到,Scope注解作用的核心是对注入器的控制,那么出现这样的效果,也就不足为奇了。

1 0
原创粉丝点击