关于Dagger2使用的基础如果你还不了解,可以参考我的上一篇文章解锁Dagger2使用姿势(一),这有助于你理解本篇文章。

OK,我们在上篇文章介绍另外Dagger2使用过程中四个基本的注解,分别是@Module、@Provides、@Inject以及@Component。今天我想来说说Dagger2中另外一个注解,那就是@Scope注解。看网上的资料,大家基本上都知道@Scope是用来给依赖划定作用域的,那我今天就来来说说这个作用域的问题。

首先Dagger2中有一个现成的作用域注解,那就是@Singleton,其实这个@Singleton还是由Java提供的。那么这个注解的作用域就是让我们的依赖成为单例模式。比如下面一个例子:假设我有一个用户对象,如下:

public class User {

	....
.... @Inject
public User() {
} ....
.... }

我这里暂时先用@Inject来注解这个用户对象,避免使用Module,然后我需要一个Component来注入这个User对象到我的Activity中,我的Component如下:

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

OK,然后我在我的MainActivity中初始化User对象,并将其地址显示出来:

public class MainActivity extends AppCompatActivity {

    @Inject
User user;
@Inject
User user2;
private TextView tv;
private TextView tv2; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DaggerActivityComponent.builder().build().inject(this);
tv = ((TextView) findViewById(R.id.tv));
tv2 = ((TextView) findViewById(R.id.tv2));
tv.setText(user.toString());
tv2.setText(user2.toString());
}
}

显示结果如下:

OK ,大家看到这完全是两个不同的对象,两个对象的引用地址完全不一样。那如果我想让User变为一个单例模式该怎么办呢?其实很简单,添加上@Singleton注解就可以了,在哪里添加呢?两个地方:

1.给User类添加上@Singleton注解:

@Singleton
public class User { ....
.... @Inject
public User() {
} ....
.... }


2.给ActivityComponent添加上@Singleton注解

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

如此之后我再运行,结果如下:

OK,这个时候User对象就会以单例形式存在于我的App中了。OK,那如果我的项目中有Module,又该如何使我的User对象单例呢?

很简单,在Module中提供User对象,提供User对象的方法需要有单例注解:

@Module
public class UserModule {
@Provides
@Singleton
User providesUser() {
return new User();
}
}

这个时候User对象上的注解就都可以去掉了,然后稍微修改一下ActivityComponent,如下:

@Singleton
@Component(modules = UserModule.class)
public interface ActivityComponent {
void inject(MainActivity activity);
}

然后MainActivity中初始化的代码也要稍微修改一下下:

DaggerActivityComponent.builder().userModule(new UserModule()).build().inject(this);

然后再运行,依然是单例模式。

OK,那我们知道@Singleton注解实际上实现的是一个全局单例模式,在实际开发中我们可能还需要一种局部单例的控件(这个应该是更常用),比如说我们有三个Activity,MainActivity,BActivity和CActivity,我们想让MainActivity和BActivity共享同一个实例,而让CActivity获取另外一个实例,这又该怎么实现呢?在Dagger2中,我们可以通过自定义Scope来实现局部单例。爽歪歪吧!OK,那就动手吧:

首先让我们先来定义一个局部作用域:

@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface UserScope {
}

然后在我们的UserModule和ActivityComponent中应用该局部作用域:

@Module
public class UserModule {
@Provides
@UserScope
User providesUser() {
return new User();
}
}

@UserScope
@Component(modules = UserModule.class)
public interface ActivityComponent {
void inject(MainActivity activity); void inject(BActivity activity);
}

请大家注意,我的ActivityComponent作为一个注入器只可以向MainActivity和BActivity两个Activity中注入依赖,不可以向CActivity中注入依赖。最后,要让该局部作用域产生单例效果,需要我们在自定义的Appliation类中来初始化这个Component,如下:

public class MyApp extends Application {
ActivityComponent activityComponent;
@Override
public void onCreate() {
super.onCreate();
activityComponent = DaggerActivityComponent.builder().userModule(new UserModule()).build();
} ActivityComponent getActivityComponent(){
return activityComponent;
}
}

接下来我们在MainActivity和BActivity中注入依赖,MainActivity如下:

    @Inject
User user;
@Inject
User user2;
private TextView tv;
private TextView tv2; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// DaggerActivityComponent.builder().userModule(new UserModule()).build().inject(this);
((MyApp) getApplication()).getActivityComponent().inject(this);
tv = ((TextView) findViewById(R.id.tv));
tv2 = ((TextView) findViewById(R.id.tv2));
tv.setText(user.toString());
tv2.setText(user2.toString());
}

BActivity如下:

    @Inject
User user; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_b);
((MyApp) getApplication()).getActivityComponent().inject(this);
TextView tv = (TextView) findViewById(R.id.tv);
tv.setText(user.toString());
}

那么如果我还想在CActivity中使用User对象该怎么办呢?再来一个CUserModule和CActivityComponent呗!

CUserModule如下:

@Module
public class CUserModule {
@Provides
User providesUser() {
return new User();
}
}

这里我没有再注明单例了哦!

CActivityComponent如下:

@Component(modules = CUserModule.class)
public interface CActivityComponent {
void inject(CActivity activity);
}

在CActivity中注入依赖:

    @Inject
User user;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_c);
DaggerCActivityComponent.builder().cUserModule(new CUserModule()).build().inject(this);
TextView tv = (TextView) findViewById(R.id.tv);
tv.setText(user.toString());
}

运行结果如下:

大家看到,MainActivity和BActivity是同一个实例,而CActivity则是另外一个实例。

那么可能会有小伙伴问@UserScope在这里到底起了什么作用?我引用网上一段话:

以下文字来源:http://blog.csdn.net/u012943767/article/details/51941872

Scope的使用,如何实现单例?

这个迷之Scope也是有点难以理解,我们在哪里使用到了Scope呢。在我们的AppComponent中添加了一个注解为@Singleton,@Singleton就是一个Scope,据说可以实现单例哟。。。难道这样就实现了单例模式?我刚刚开始是这样理解的。直到仔细的看了几遍这篇文章我才知道并不是这样的。

事实上@Sinleton中并没有创建单例的能力,那么AppComponent中提供的依赖注入是如何实现单例的呢。其实这个原理很贱单。

首先Module提供了创建实例的方法,接着AppComponent中对Module进行管理,最后AppComponent在自定义Applicaiton中被实例化了一次。

这个实例化了一次是最重要的呀。仅仅被实例化了一次,那不就是单例么。就是这么简单呀。

可能有些童靴当时就不乐意了,那既然这样都已经实现了单例,那么这个@Singltop还要来何用?不是多此一举吗。

其实@Singletop还有有一些作用的,首先一方面能让你直面的了解到这是一个单例,其次这个@Singletop能够更好的管理Modlue和Component之间的关系。

Dagger2需要保证Component和Module是匹配的,就需要用到这个注解。

OK,这就是Dagger2中@Scope注解的使用。后面我再来介绍Component之间的依赖关系。

以上。

Demo下载http://download.csdn.net/detail/u012702547/9603997

解锁Dagger2使用姿势(二) 之带你理解@Scope的更多相关文章

  1. 解锁Dagger2使用姿势(一)

    毫无疑问,Dagger2的 上手是有门槛的,有门槛是因为它里边的概念多,用起来复杂,可是一旦你学会了Dagger2的使用,你一定会爱不释手的.与ButterKnife和AndroidAnnotatio ...

  2. [转帖]从零开始入门 K8s | 手把手带你理解 etcd

    从零开始入门 K8s | 手把手带你理解 etcd https://zhuanlan.zhihu.com/p/96721097 导读:etcd 是用于共享配置和服务发现的分布式.一致性的 KV 存储系 ...

  3. 手摸手带你理解Vue的Watch原理

    前言 watch 是由用户定义的数据监听,当监听的属性发生改变就会触发回调,这项配置在业务中是很常用.在面试时,也是必问知识点,一般会用作和 computed 进行比较. 那么本文就来带大家从源码理解 ...

  4. 大白话说Java泛型(二):深入理解通配符

    文章首发于[博客园-陈树义],点击跳转到原文<大白话说Java泛型(二):深入理解通配符> 上篇文章<大白话说Java泛型(一):入门.原理.使用>,我们讲了泛型的产生缘由以及 ...

  5. 一个故事带你理解if __name__ == '__main__'

    如果你刚刚接触python,相信会在看别人的程序的时候会遇到if __name__ == '__main__'酱紫的语法,如果当时没看懂现在也一知半解的话,看下去,本文可以帮你解决这个问题. 大家都知 ...

  6. JDK1.8源码逐字逐句带你理解LinkedHashMap底层

    注意 我希望看这篇的文章的小伙伴如果没有了解过HashMap那么可以先看看我这篇文章:http://blog.csdn.net/u012403290/article/details/65442646, ...

  7. 手摸手带你理解Vue的Computed原理

    前言 computed 在 Vue 中是很常用的属性配置,它能够随着依赖属性的变化而变化,为我们带来很大便利.那么本文就来带大家全面理解 computed 的内部原理以及工作流程. 在这之前,希望你能 ...

  8. Pthread 并发编程(二)——自底向上深入理解线程

    Pthread 并发编程(二)--自底向上深入理解线程 前言 在本篇文章当中主要给大家介绍线程最基本的组成元素,以及在 pthread 当中给我们提供的一些线程的基本机制,因为很多语言的线程机制就是建 ...

  9. Android自己定义ViewGroup(二)——带悬停标题的ExpandableListView

    项目里要加一个点击可收缩展开的列表,要求带悬停标题,详细效果例如以下图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fon ...

随机推荐

  1. SQL Server 2008R2 数据库出现“可疑”导致无法访问

    日常对Sql Server 2005关系数据库进行操作时,有时对数据库(如:Sharepoint网站配置数据库名Sharepoint_Config)进行些不正常操作如数据库在读写时而无故停止数据库,从 ...

  2. 利用逻辑运算符?"三个数字比大小

    static void Main(string[] args)        {            int a, b, c;            while (true)            ...

  3. 【转】VC中对文件的读写

    原文网址:http://www.cnblogs.com/LJWJL/archive/2012/10/06/2712466.html 注意: 1.由于C是缓冲写 所以要在关闭或刷新后才能看到文件内容 2 ...

  4. servlet读取cookie问题

    String sessionid = request.getSession().getId(); // 取得当前的session id ckSessionid = new Cookie("s ...

  5. 提取WORD中的所有InlineShape图片并保存成文件

    InlineShape表示的类型其实不只是图片,还包括OLE, ACTIVE X等. 下面是MSDN中的定义:Represents an object in the text layer of a d ...

  6. DataContractJsonSerializer类

    DataContractJsonSerializer类 DataContractJsonSerializer类同样是提供JSON序列化的类.而且貌似有几个方法还和XML有点点关系. 注意用此类要引用S ...

  7. UVa 11752 - The Super Powers 数学

    请看这个说明http://blog.csdn.net/u014800748/article/details/45914353 #define _CRT_SECURE_NO_WARNINGS #incl ...

  8. Linux Kernel Schduler History And Centos7.2's Kernel Resource Analysis

    本文分为概述.历史.el7.2代码架构图解三部分. 解决的问题: a.Kernel调度发展过程: b.以架构图的方式,详解el7.2具体调度实现.内核线程模型.调度时间片计算,以及探究整个Kernel ...

  9. 【JS】Intermediate6:jQuery

    1.jQuery is far and away the most popular DOM library Used to allow modification and control of the ...

  10. 六种简单方法提升ASP.NET Web API性能

    ASP.NET Web API 是非常棒的技术.编写 Web API 十分容易,以致于很多开发者没有在应用程序结构设计上花时间来获得很好的执行性能. 在本文中,我将介绍8项提高 ASP.NET Web ...