Dagger 2从浅到深(五)

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


Demo地址:

  1. DaggerLearn
  2. Kotlin-Dagger-2-Retrofit-Android-Architecture-Components

总所周知的是,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()方法时的效果:

@TodoScope
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());

    }

    ***
}

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

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

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

这里写图片描述

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

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值