热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Dagger2整理一波

在讲Dagger2之前呢,我先列一个事例代码,看看用了Dagger2之后有什么不一样的地方。publicclassA{privateBb;privateCc;publicA(){b

在讲Dagger2之前呢,我先列一个事例代码,看看用了Dagger2之后有什么不一样的地方。

public class A {
private B b;
private C c;
public A() {
b = new B();
c = new C();
}
}
public class B {
}
public class C {
}

该事例代码在A中引用了B和C,这个没什么,那如果当B和C业务复杂了呢,需要增加属性:

public class B {
private String name;
public B(String name) {
this.name = name;
}
}
public class C {
private int age;
public C(int age) {
this.age = age;
}
}

那是不是A里面的代码也跟着发生变化了呢,是的,传参变了,那调用方肯定也发生变化了。所以说这种业务逻辑的改变是说不准的。下面看看Dagger2是怎么写这种变动的逻辑:

public class B {
@Inject
public String name;
@Inject
public B() {
}
}
public class C {
@Inject
public int age;
@Inject
public C() {
}
}
public class A {
@Inject
public B b;
@Inject
public C c;
@Inject
public A() {
// b = new B("张三");
// c = new C(12);
}
}

上面改动的代码中,A中依赖了B和C,B和C中的构造方法提供了@Inject注解来说明自己是被Dagger2来生成,同样A中也说明了依赖的B和C是被Dagger2来管理起来了。注意上面如果需要用到@Inject注解,属性是不能用private来修饰的。仅有上面的代码,是没法动态生成A的,此时需要借助@Component注解和@Module注解:

@Component(modules = AbcMondel.class)
public interface Abc {
A getA();
}
@Module
public class AbcMondel {
@Provides
public String provideName() {
return "张三";
}
@Provides
public int provideAge() {
return 10;
}
}

其实这里可以看做是Component注解是主要组合@Module注解的,而@Module就是专门提供模型和数据的。当初始化B和C的时候,发现Module中有提供参数age和name,因此直接使用该处的内容。在调用方直接去生成A:

《Dagger2整理一波》 image.png

其实对于这种生成数据肯定在实际业务逻辑中不行,比如说我们的数据来自于网络层,数据肯定得从activity中传过来的呀,那此时怎么去传这个值呢:

@Module
public class AbcMondel {
private String name;
private int age;
public AbcMondel(String name, int age) {
this.name = name;
this.age = age;
}
@Provides
public String provideName() {
return name;
}
@Provides
public int provideAge() {
return age;
}
}

这里主要改动的地方AbcMondel,通过构造器将参数传进来。那调用的地方是啥样的:

《Dagger2整理一波》 image.png

上面多了一个abcMondel方法,该方法就是根据Module来生成的。
其实上面的B和C对象也可以直接放在model中通过Provides来生成,具体怎么玩看如下代码:

public class B {
public String name;
public B(String name) {
this.name = name;
}
//无参的注入构造器,为了验证dagger2是以inject注入为主,还是 以Provides注解的注入方式为主
@Inject
public B() {
this.name = "李四";
}
}
public class C {
public int age;
@Inject
public C() {
}
public C(int age) {
this.age = age;
}
}
public class Cc extends C {
@Inject
public Cc() {
super(100);
}
public Cc(int age) {
this.age = age;
}
}
@Module
public class AbcMondel {
// private String name;
// private int age;
// public AbcMondel(String name, int age) {
// this.name = name;
// this.age = age;
// } //Provides直接提供的是B的有参构造
@Provides
public B provideB() {
return new B("xc");
}
}
@Module
public class AbcMondel {
// private String name;
// private int age;
// public AbcMondel(String name, int age) {
// this.name = name;
// this.age = age;
// }
@Provides
public B provideB() {
return new B("xc");
}
@Provides
public C provideC(Cc c) {
return c;
}
}

《Dagger2整理一波》 image.png

看到打印的数据没,name是通过Provides注解传递进去的,age是通过Cc类里面获取到的,因此这里可以得到两个结论,
如果inject和Provides同时提供了依赖,那此时优先去看Provides有没有提供相应的依赖,没有的话才去找inject相应的构造器;再个就是看到C提供的依赖没,他是通过传参的形式生成依赖的,所以从B和C生成依赖的方式也大概知道什么时候通过传参的形式,什么时候通过new的形式

new的形式呢,是通过手动去new,说明该类的构造器没有被依赖,直接通过形参的形式呢,说明该类已经在构造器上标注了@inject注解,因此像我们自己写的类就通过传参的形式,因为自己写的一般构造器上都有inject注解,像第三方的sdk没有办法改动源码,因此只能通过new的形式生成注解

Component通过传参的形式实现注入

这里用android中常用的mvp框架来做例子:
首先写好p层:

public class MainPresenter {
private static final String TAG = MainPresenter.class.getSimpleName();
MainActivityView.Iview mainActivityView;
@Inject
public MainPresenter(MainActivityView.Iview mainActivityView) {
this.mainActivityView = mainActivityView;
}
public void loadPage() {
mainActivityView.loadStart();
Log.d(TAG, "loadPage");
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
mainActivityView.loadEnd();
}
}, 3000);
}
}

p层有MainActivityView.Iview引用,实际上就是MainActivity的实例,那此时肯定要在Module中提供该形参的实例:

@Module
public class PresenterModel {
private final MainActivityView.Iview mView;
public PresenterModel(MainActivityView.Iview view) {
mView = view;
}
@Provides
MainActivityView.Iview provideMainView() {
return mView;
}
}

前面已经说过,如果该类是系统定义的类,那么此时是可以通过new的方式提供给注入的参数,如果不是系统的可以通过在该类的构造器上面加上@inject注解。显然这个MainActivityView.Iview是activity实例,因此需要我们new或者传参进来,很显然MainActivity实例是不允许直接new的,因此需要传参进来。
Component部分代码:

@Component(modules = PresenterModel.class)
public interface PresenterComponent {
void inject(MainActivity mainActivity);
// @Component.Builder
// interface Builder {
// PresenterComponent.Builder view(MainActivityView.Iview view);
//
// PresenterComponent build();
// }
}

activity中的代码:

DaggerPresenterComponent.builder().presenterModel(new PresenterModel(this)).build().inject(this);

主要就这么一句,相信大家对mvp简单的架子搭建肯定是没问题了。
对于该框架大家需要多用,自然就比较顺手用了。

Singleton注解

其实从字面意思就大致明白是什么作用了,下面用一个事例来说明下该注解的意思:

《Dagger2整理一波》 image.png

这个是A类上加了singleton注解,还有在相应的Component接口类也需要加上该注解才能编译成功:

《Dagger2整理一波》 image.png

在MainActivity中可以验证这一注解:

《Dagger2整理一波》 image.png

这里改变了b中的name字段,那么可以看下两个name的变化:

《Dagger2整理一波》 image.png

所以从图上看也确实验证了这一结论。其实这里的单例是跟Component接口一起走的,因为Singleton注解的单例范围就是在某一个Component接口内的,跨Component是没有单例的说法。

说到这里其实很想知道大部分项目中用到了自定义的属性,比如说:

《Dagger2整理一波》 image.png

这里定义的注解和singleton注解是一样的,因此可以说明它的作用和singleton是一样的,为了保证在Component作用域内该对象一直处于单例的状态。

更多内容点击

关于mvp的例子大家可以阅读这里


推荐阅读
  • 先看官方文档TheJavaTutorialshavebeenwrittenforJDK8.Examplesandpracticesdescribedinthispagedontta ... [详细]
  • Java太阳系小游戏分析和源码详解
    本文介绍了一个基于Java的太阳系小游戏的分析和源码详解。通过对面向对象的知识的学习和实践,作者实现了太阳系各行星绕太阳转的效果。文章详细介绍了游戏的设计思路和源码结构,包括工具类、常量、图片加载、面板等。通过这个小游戏的制作,读者可以巩固和应用所学的知识,如类的继承、方法的重载与重写、多态和封装等。 ... [详细]
  • 本文介绍了闭包的定义和运转机制,重点解释了闭包如何能够接触外部函数的作用域中的变量。通过词法作用域的查找规则,闭包可以访问外部函数的作用域。同时还提到了闭包的作用和影响。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • JavaSE笔试题-接口、抽象类、多态等问题解答
    本文解答了JavaSE笔试题中关于接口、抽象类、多态等问题。包括Math类的取整数方法、接口是否可继承、抽象类是否可实现接口、抽象类是否可继承具体类、抽象类中是否可以有静态main方法等问题。同时介绍了面向对象的特征,以及Java中实现多态的机制。 ... [详细]
  • 本文介绍了Java高并发程序设计中线程安全的概念与synchronized关键字的使用。通过一个计数器的例子,演示了多线程同时对变量进行累加操作时可能出现的问题。最终值会小于预期的原因是因为两个线程同时对变量进行写入时,其中一个线程的结果会覆盖另一个线程的结果。为了解决这个问题,可以使用synchronized关键字来保证线程安全。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • #前言AndroidArchitectureComponents是谷歌在GoogleIO2017发布的。官方的描述:https:developer.android.google.c ... [详细]
author-avatar
永川青峰_915
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有