@Scope 看这一篇就够了——Dagger2 (二)_薛瑄的博客-程序员秘密

技术标签: singleton  Dagger 2  android  scope  dagger2  

转载请标明出处:http://blog.csdn.net/xx326664162/article/details/67640509 文章出自:薛瑄的博客

Dagger2 系列:

Dagger2 入门详解(一)

@Scope 看这一篇就够了——Dagger2 (二)

1、@Scope 到底有什么作用

scope 字面意思是范围,标志一个注入器/对象的使用范围,很多文章说成生命周期也是可以的。比如,单例模式,局部单例模式等等。

在Dagger 2中

1、@Singleton可以保持类的单例。
2、@ApplicationScope注解的Component类与Applicaiton对象的生命周期一致。
3、@ActivityScope注解的Component类与Activity的生命周期一致

scope可以给我们带来“局部单例”,生命周期取决于scope自己。

但是需要弄清楚的是 - Dagger 2默认并不提供@ActivityScope 、 @ApplicationScope 这些注解。这些只是最常用的自定义Scope。只有@Singleton scope是默认提供的(由Java自己提供)。

2、@Scope 的使用

使用也很简单,比如使用@Singleton 。

@Module
class MachineModule{
    @Singleton   //1.添加@Singleton标明该方法产生只产生一个实例
    @Provides
    Machine provideFruitJuiceMachine(){
        return new FruitJuiceMachine();
    }
}
@Singleton  //2.添加@Singleton标明该Component中有Module使用了@Singleton
@Component(modules=MachineModule.class)
class JuiceComponent{
    void inject(Container container)
}

public class Test{
    
    public static void main(String... args){
        JuiceComponent c1=DaggerJuiceComponent.create();
        c1.inject(container1);  
        c1.inject(container2);  
        //由于制造machine的方法使用了@Singleton,所以先后注入container1,container2中的machine相同
        System.out.println(conainter1.machine==conainter2.machine);//true
    }
}

上面的例子可以看到,实现单例需要两步 :

  1. 在Module对应的Provides方法标明@Singleton
  2. 同时在Component类标明@Singleton

3、@Scope 的用武之地

为了更好地去理解Dagger 2中的scope,我们直接进入实践案例。我们将要去实现比Application/Activity scope更加复杂一点的scope。假如现在需要三种scope:

@Sigleton - application scope 全局的单例对象
@UserScope - 用于与当前用户联系起来的类实例的scope(在真实的app中可以是当前登录的用户)。
@ActivityScope - 生命周期与Activity(在我们例子中的呈现者)一致的实例的scope

请注意@Sigleton可以保证是单例,是dagger2内部控制的。(主要代码详见dagger2中dagger-2.2-sources.jar!\dagger\internal\ScopedProvider.java中的get()函数)

@UserScope,@ActivityScope 控制实例的生命周期,需要程序员自己去控制对应的Component。

使用方法参数获取用户数据的类(在我们的例子中是RepositoriesManager),我们可以通过构造参数(它将通过依赖图表提供)的方式来获取User实例并在需要的时候被初始化,而不是在app启动的时候创建它。这意味着RepositoriesManager可以在我们从Github API获取到用户信息(在RepositoriesListActivity呈现之前)之后被创建。

这里有个我们app中scopes和components呈现的简单图表。

这里写图片描述

单例(Application scope)是最长的scope(在实践中是与application一样长)。

UserScope作为Application scope的一个子集scope,它可以访问它的对象(我们可以从父scope中得到对象)。

ActivityScope(生命周期与Activity一致)也是如此 - 它可以从UserScope和ApplicationScope中得到对象。

@Scope生命周期的例子

这里有一个我们app中scope生命周期的案例:

这里写图片描述

单例的生命周期是从app启动后的所有时期,当我们从Github API(在真实app中是用户登录之后)得到了User实例时UserScope被创建了,然后当我们回退到SplashActivity(在真实app中是用户退出之后)时被销毁。

demo地址https://github.com/frogermcs/GithubClient

4、@Singleton

@Singleton就是一种Scope注解,也是Dagger2唯一自带的Scope注解,使用它就可以实现单例模式。

这篇文章解锁Dagger2使用姿势(二) 之带你理解@Scope用代码证明了,使用@Singleton就可以实现单例模式。demo:https://github.com/JantHsueh/Dagger2

下面是@Singleton的源码

@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton{
    }

可以看到定义一个Scope注解,必须添加以下三部分:

@Scope :注明是Scope
@Documented :标记在文档
@Retention(RUNTIME) :运行时级别

单例的保存位置

Java中,单例通常保存在一个静态域中,这样的单例往往要等到虚拟机关闭时候,该单例所占用的资源才释放。但是,Dagger通过Singleton创建出来的单例并不保持在静态域上,而是保留在Component实例中。要理解这一点,请看下面代码,续上文中的例子

public class Test{
    public static void main(String... args){
        //c1,c2是不同对象,它们各自缓存machine
        JuiceComponent c1=DaggerJuiceComponent.create();
        JuiceComponent c2=DaggerJuiceComponent.create();
        c1.inject(container1);
        c1.inject(container2);
        c2.inject(container3);
        c2.inject(container4);
        System.out.println(conainter1.machine==conainter2.machine);//true
        System.out.println(conainter2.machine==conainter3.machine);//false
        System.out.println(conainter3.machine==conainter4.machine);//true
        System.out.println(conainter4.machine==conainter1.machine);//false
    }
}

c1前后两次分别注入container1,container2,每个Component对象保留各自的单例对象,

而container1,container2都是使用c1来注入machine,所以他们的machine对象是相同的。
而container2、container3分别使用c1,c2来注入machine,所以他们的machine对象是不同的。

5、自定义@Scope

对于Android,我们通常会定义一个针对整个APP全生命周期的@PerApp的Scope注解,通过仿照@Singleton

@Scope
@Documented
@Retention(RUNTIME)
public @interface PerApp{
    }

你可能会发现,这个自定义的@Scope 和@Singleton代码完全一样,那@PerApp是不是也能具有实现单例模式的功能?

答案是肯定的

那你可能会有疑问,既然功能都是一样的,干嘛还自定义@Scope ,回忆一下上面第三点使用场景,你会明白,不同的@Scope ,定义单例对象的生命周期,也就是使用范围。在写代码时,程序员更加清楚什么时候创建Component,什么时候结束。

总结起来有以下两点好处:

  • 更好的管理ApplicationComponent和Module之间的关系,Component和Component之间的依赖和继承关系。如果关系不匹配,在编译期间会报错,详解第6点。

  • 代码可读性,让程序猿更好的了解Module中创建的类实例的使用范围。

6、使用@Scope的一些经验

1、@Component关联的@Module中的任何一个@Provides有@scope,则该整个@Component要加上这个scope。否则在暴露或者注入时(不暴露且不注入时,既不使用它构造对象时,不报错),会有如下错误

Error:(13, 1) 错误: cn.xuexuan.newui.di.component.ActivityComponent (unscoped) may not reference scoped bindings:
@Singleton @Provides android.app.Activity cn.xuexuan.newui.di.module.ActivityModule.getActivity()

2、@Component的dependencies与@Component自身的scope不能相同,即组件之间的scope不能相同,否则出现下面错误。

3、@Singleton的组件不能依赖其他scope的组件,但是其他scope的组件可以依赖@Singleton组件。否则出现下面错误。
4、没有scope的不能依赖有scope的组件。否则出现下面错误。

Error:(21, 1) 错误: com.android.example.devsummit.archdemo.di.component.MyTestComponent (unscoped) cannot depend on scoped components:
@com.android.example.devsummit.archdemo.di.scope.ActivityScope com.android.example.devsummit.archdemo.di.component.MyTestComponentX

5、一个component不能同时有多个scope(Subcomponent除外),否则出现下面的错误

Error:Execution failed for task ‘:app:compileDebugJavaWithJavac’.
java.lang.IllegalArgumentException: com.android.example.devsummit.archdemo.di.component.MyTestComponent was annotated with more than one @Scope annotation

最后奉上我所使用的测试demo:
https://github.com/JantHsueh/Dagger2
https://github.com/frogermcs/GithubClient

参考:

Android注入框架Dagger2学习笔记

Android:dagger2让你爱不释手-重点概念讲解、融合篇

解锁Dagger2使用姿势(二) 之带你理解@Scope

Android常用开源工具(2)-Dagger2进阶

使用Dagger 2依赖注入 - 自定义Scope

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xx326664162/article/details/67640509

智能推荐

【存储测试】cosbench存储性能测试工具_cosbench性能测试_Luxf0的博客-程序员秘密

cosbench - Cloud Object Storage Beachmark,是Intel开发的一个对象存储基准性能测试工具,支持OpenStack* Swift, Amazon* S3, Amplidata v2.3, 2.5 and 3.1, Scality*, Ceph, CDMI,Google* Cloud Storage, Aliyun OSS对象存储

FPGA学习-基于FPGA的高速串行通信GTX知识梳理_Hack电子的博客-程序员秘密

对于XILINX,7系列FPGA,关于GTX核对配置见PG168,了解GTX内部结构及更多的知识见ug476。 以7系列XC7k325t-ffg900为例,见各ug476,351页。可看到该芯片共有4个高速bank,分别为115 116 117 118;每个bank又有4组收发模块和两组时钟模块。1,GTX时钟和复位 (1)时钟源: GTX...

一款集成度高的渗透工具:Railgun_railgun工具_Mr. M2021的博客-程序员秘密

Railgun为一款GUI界面的渗透工具,将部分人工经验转换为自动化,集成了渗透过程中常用到的一些功能目前集成了端口扫描、端口爆破、web指纹扫描、漏洞扫描、漏洞利用以及编码转换功能。信息收集端口扫描界面如下[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LjQyOIhY-1623550020985)(https://image.3001.net/images/20210517/1621256630_60a269b634375ad903802.png!small)]

C++ opencv之像素操作之逻辑操作(bitwise_and,bitwise_xor,bitwise_or,bitwise_not)_阿超没有蛀牙的博客-程序员秘密

这篇博客我们来学习像素操作之逻辑操作。一、知识点主要的知识点是:对图像中的位操作:- bitwise_and //按位与- bitwise_xor //按位异或- bitwise_or //按位或取反操作:- bitwise_not //取反二、函数原型1、按位与操作bitwise_and(InputArray src1, InputArray src2,OutputArray dst, InputArray mask=noArray());//dst

如何用css 将span 右对齐_tuber的博客-程序员秘密

如何用css 将div 中的span 右对齐floatflex & justify-contentabsolute添加floatdiv { span { float: right; }}添加flexdiv { display: flex; justify-content: space-between;}添加absolutediv {

随便推点

谈谈对代码审查Code Review的简单认识_不了解功能的可以做代码审核吗_王小二(海阔天空)的博客-程序员秘密

谈谈对代码审查Code Review的简单认识Code Review(代码审查)是软件开发中的最佳实践之一,可以有效提高整体代码质量,及时发现代码中可能存在的问题。包括像Google、微软这些公司,Code Review都是基本要求,代码合并之前必须要有人审查通过才行。一、Code Review有什么好处?从团队知识共享的角度一个开发团队中,水平有高有低,每个人侧重的领域也有不同...

c语言 freopen txt_C语言中数据输入输出到文件操作freopen()函数(1)_weixin_28940939的博客-程序员秘密

例题一、把短句 “Hello World!” 保存到磁盘文件f1.txt中。#include #includeint main(){FILE*fp; /*定义文件指针*/if( ( fp = fopen("f1.txt", "w") ) == NULL){ /*打开文件*/printf("File open error!...

ZigBee无线Soc EFR32MG Series 2 (MG21)定时器特征_weixin_30507269的博客-程序员秘密

关键词:ZigBee 3.0,ZigBee,EFR32MG21, MG21, TIMER, 定时器, PWM, CounterSilicon Labs于2019年推出的全新Zigbee芯片,EFR32MG21 在硬件上支持多达4个定时器,每个定时器支持3-4路,每一路可以配置为输入或者PWM输出。而且定时器还可以组合为32位,或者拆分为16位。还支持死区插入模块功能,用来作电机...

resquest和response_linweihan1984的博客-程序员秘密

[color=red]Request对象:服务器端用于接受客户端请求内容的[/color] 所属接口:javax.servlet.http.HttpServletRequest[color=red]Response 对象:服务器回应客户断的请求[/color] 所属接:javax.servlet.httpServletResponseresponse在开...

Rocket.chat快速安装部署_penguinhd的博客-程序员秘密

准备1.CentOs 7.6 x86_642.Mongodb 4.0.93.NodeJs4.Rocket.Chat最新版5.服务器开放3000端口首先执行下方代码cat << EOF | sudo tee -a /etc/yum.repos.d/mongodb-org-4.0.repo[mongodb-org-4.0]name=MongoDB Repositorybaseurl=https://repo.mongodb.org/yum/redhat/7/mongodb-

Redis持久化之RDB与AOF详解_aof文件在什么时候转化成为rdb_NeverOW的博客-程序员秘密

️RDB和AOF机制简介RDB和AOF是redis数据持久化的两种机制;当然实际场景下还会使用这两种的混合模式为了防止数据丢失以及服务重启时能够恢复数据为什么需要持久化Redis是个基于内存的数据库。服务器一旦宕机,内存中的数据将全部丢失当然也可以从后端数据库恢复这些数据,但是后端数据库性能一般比不上redis,大数据量的恢复会对数据库带来巨大压力,所以应该避免从后端数据库中恢复数据Redis持久化有哪些方式呢?为什么我们需要重点学RDB和AOF?RDBAOF

推荐文章

热门文章

相关标签