Android   发布时间:2022-04-28  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了dagger2使用方法教程之简明讲解大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

前言

Dagger 这个库的取名不仅仅来自它的本意“匕首”,同时也暗示了它的原理。Jake Wharton 在对 Dagger 的介绍中指出,Dagger 即 DAG-er,这里的 DAG 即数据结构中的 DAG――有向无环图(Directed Acyclic Graph)。也就是说,Dagger 是一个基于有向无环图结构的依赖注入库,因此Dagger的使用过程中不能出现循环依赖。

Android开发从一开始的MVC框架,到MVP,到MVVM,不断变化。现在MVVM的data-binding还在实验阶段,传统的MVC框架Activity内部可能包含大量的代码,难以维护,现在主流的架构还是使用MVP(Model + View + Presenter)的方式。但是 MVP 框架也有可能在Presenter中集中大量的代码,引入DI框架Dagger2 可以实现 Presenter 与 Activity 之间的解耦,Presenter和其它业务逻辑之间的解耦,提高模块化和可维护性。

现在的公司项目用到了Dagger2,之前只是稍微了解一些,没有用过,然后查了查资料,整理如下,方便快速上手

四个基本注解

1、@Inject 主要有两个作用,一个是使用在构造函数上,通过标记构造函数让Dagger2来使用(Dagger2通过Inject标记可以在需要这个类实例的时候来找到这个构造函数并把相关实例new出来)从而提供依赖,另一个作用就是标记在需要依赖的变量让Dagger2为其提供依赖。

2、@module 用Module标注的类是专门用来提供依赖的。有的人可能有些疑惑,看了上面的@Inject,需要在构造函数标记才能提供依赖,那么如果我们需要提供的类构造函数无法修改怎么办,比如一些jar包里的类,我们无法修改源码。这时候就需要使用Module了。Module可以给不能修改源码的类提供依赖,当然,能用Inject标注的通过Module也可以提供依赖。

3、@Provides 用Provides来标注一个方法,该方法可以在需要提供依赖时被调用,从而把预先提供好的对象当做依赖给标注了@Inject的变量赋值。provides主要用于标注Module里的方法

4、@Component 一般用来标注接口,被标注了Component的接口在编译时会产生相应的类的实例来作为提供依赖方和需要依赖方之间的桥梁,把相关依赖注入到其中。

四个扩展注解

1、@Qulifier 这里有个概念,叫依赖迷失,就是在Module注解的类里,有2个Provides都提供某个类的实例,这时候不用@Qulifier注解的话Component会不知道用哪个实例,这时候就要使用@Qulifier,下面直接提供代码

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface A {}
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
public @interface B {}
@module
public class SimpleModule {
 @Provides
 @A
 Cooker provideCookerA(){
 return new Cooker("James","Espresso");
 }

 @Provides
 @B
 Cooker provideCookerB(){
 return new Cooker("Karry","Machiato");
 }
}
public class ComplexMaker implements CoffeeMaker {
 Cooker cookerA;
 Cooker cookerB;
 @Inject
 public ComplexMaker(@A Cooker cookerA,@B Cooker cookerB){
 this.cookerA = cookerA;
 this.cookerB = cookerB;
 }
}

2、@Named 和@Qulifier一样,并且@Named就是继承@Qulifier的,而且用起来比@Qulifier方便,示例代码如下:

@module
public class MainModule {
 @Provides
 @Named("red")
 public Cloth getRedCloth() {
 Cloth cloth = new Cloth();
 cloth.setColor("红色");
 return cloth;
 }

 @Provides
 @Named("blue")
 public Cloth getBlueCloth() {
 Cloth cloth = new Cloth();
 cloth.setColor("蓝色");
 return cloth;
 }

 @Provides
 public Clothes getClothes(@Named("blue") Cloth cloth){
 return new Clothes(cloth);
 }
}
public class MainActivity extends AppCompatActivity {
 ...
 @Inject
 @Named("red")
 Cloth redCloth;
 @Inject
 @Named("blue")
 Cloth blueCloth;
 @Override
 protected void onCreate(Bundle savedInstanceStatE) {
 ...
 tv.setText("我现在有" + redCloth + "和" + blueCloth );
 }
}

3@Scope 局部单例,意思就是在被注入类里只有一个该类的实例,局部范围是啥,那就是它生命周期范围内。直接上代码

//PerActivity.java
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerActivity {}
//Activitymodule.java
@module
public class Activitymodule {
 @Provides
 CoffeeShop provideCoffeeShop(){
 return CoffeeShop.geTinstance();//一个普通的单例
 }

 /**
 * 直接在这里说结果,@PerActivity是用@Scope注解的,除了在这里注解还需要在用到该Module类的Component的类名上方也要注解,然后该实例在注入到某个类里的时候用同一个Component就会不管有几个字段都会只有一个实例。注意:如果用不同的Component实例的话仍然会新的CookerFactory实例,单例CookerFactory只存在一个Component实例里。所以叫局部单例。
 */
 @Provides
 @PerActivity
 CookerFactory provideCookerFactory(){
 return new CookerFactory();
 }

 @Provides
 CookerFactorymulty provideCookerFactorymulty(){
 return new CookerFactorymulty();//非单例
 }
}
//CoffeeShop.java
public class CoffeeShop {
 private static CoffeeShop INSTANCE;
 private CoffeeShop(){
 Log.d("TAG","CoffeeShop New Instance");
 }

 public static CoffeeShop geTinstance(){
 if(INSTANCE == null){
 INSTANCE = new CoffeeShop();
 }
 return INSTANCE;
 }
}

//CookerFactory.java
public class CookerFactory {
 public CookerFactory(){
 Log.d("TAG","CookerFactory New Instance");
 }
}

//CookerFactorymulty.java
public class CookerFactorymulty {
 public CookerFactorymulty(){
 Log.d("TAG","CookerFactorymulty New Instance");
 }
}
//除了在Module的Provides方法里写上@Scope还需要在Component类名上方写上,这里自定义的@Scope名字叫PerActivity
@PerActivity
@Component(modules = {Activitymodule.class})
public interface ActivityComponent {
 void inject(MainActivity simpleActivity);
}
public class MainActivity extends Activity {
 ActivityComponent activityComponent;
 @Inject
 CoffeeShop coffeeShop1;

 @Inject
 CoffeeShop coffeeShop2;

 @Inject
 CookerFactory cookerFactory1;

 @Inject
 CookerFactory cookerFactory2;

 @Inject
 CookerFactorymulty cookerFactorymulty1;

 @Inject
 CookerFactorymulty cookerFactorymulty2;

 @Override
 protected void onCreate(Bundle savedInstanceStatE) {
 super.onCreate(savedInstanceStatE);
 setContentView(R.layout.activity_main);
 activityComponent = DaggerActivityComponent.builder()
 //下面这句话可以不写,因为Module有认构造函数。如果Module的构造器里有参数,并且该参数不是注入进去的,就需要用类似下面的方法手动设置实例到Component中
 .activitymodule(provideModule())
 .applicationComponent(MyApplication.getComponent()).build();
 activityComponent.inject(this);
 coffeeFactory.run();
 }
 
 private Activitymodule provideModule(){
 return new Activitymodule();
 }
}

运行结果

07-11 16:53:27.978 1927-1927/? D/TAGs CoffeeShop New Instance
07-11 16:53:27.978 1927-1927/? D/TAGs CookerFactory New Instance
07-11 16:53:27.978 1927-1927/? D/TAGs CookerFactorymulty New Instance
07-11 16:53:27.978 1927-1927/? D/TAGs CookerFactorymulty New Instance

依赖:dependencies

Component依赖Component的情况下,两个Component的@Scope不能相同,否则会编译错误,为什么这么设计我还不是很清楚,有知道的小伙伴请告诉我谢谢。

依赖的示例代码如下:

//Person.java
public class Person {
}

//PerActivity.java
@Scope
@Retention(RetentionPolicy.RUNTIME)
public @interface PerActivity {}

//BaseModule.java
@module
public class BaseModule {

 @Singleton
 @Provides
 public Person providePerson(){
 return new Person();
 }
}

//Module1.java
@module
public class Module1 {

}

//Module2.java
@module
public class Module2 {

}

//BaseComponent.java
@Singleton
@Component(modules = BaseModule.class)
public interface BaseComponent {
 public Person providePerson();
}

//Component1.java
@PerActivity
//@Singleton
//因为依赖(dependencies)的BaseComponent中用到了@Singleton,所以这个Component就不能再用了,否则会编译错误,为什么这么设计还不是很清楚
@Component(modules = Module1.class,dependencies = BaseComponent.class)
public interface Component1 {
 void inject(TestScopeActivity1 simpleActivity);
}

//Component2.java
@PerActivity
//@Singleton 为什么不能用?原理同上
@Component(modules = Module2.class,dependencies = BaseComponent.class)
public interface Component2 {
 void inject(TestScopeActivity2 simpleActivity);
}

//MyApplication.java
public class MyApplication extends Application {

 private static BaseComponent baseComponent;

 @Override
 public void onCreate() {
 super.onCreate();
 baseComponent = DaggerBaseComponent.builder().build();
 }

 public static BaseComponent getBaseComponent() {
 return baseComponent;
 }
}

//TestScopeActivity1.java
public class TestScopeActivity1 extends Activity {

 @Inject
 Person p = null;

 @Override
 protected void onCreate(Bundle savedInstanceStatE) {
 super.onCreate(savedInstanceStatE);
 setContentView(R.layout.activity_main);
 DaggerComponent1.builder().baseComponent(MyApplication.getBaseComponent()).build().inject(this);
 TextView textView = findViewById(R.id.textView);
 textView.setText(p.toString());
 textView.setOnClickListener(new View.onClickListener() {
  @Override
  public void onClick(View v) {
  startActivity(new Intent(TestScopeActivity1.this,TestScopeActivity2.class));
  }
 });
 }
}

//TestScopeActivity2.java
public class TestScopeActivity2 extends Activity {

 @Inject
 Person p = null;

 @Override
 protected void onCreate(Bundle savedInstanceStatE) {
 super.onCreate(savedInstanceStatE);
 setContentView(R.layout.activity_main);
 DaggerComponent2.builder().baseComponent(MyApplication.getBaseComponent()).build().inject(this);
 TextView textView = findViewById(R.id.textView);
 textView.setText(p.toString());
 }
}

daggar2如何选择依赖呢,按照这样的顺序

当Component调用inject方法的时候,会搜索被注入类中用@Inject注解的字段,然后会在该Component中查找在@Component(modules=。。。)注解中注册的Module,如果搜索到Module有@Provides注解的方法提供该@Inject注解的字段所需的实例,就调用相应的方法完成注入,否则就查找所有用@Inject注解构造函数的类,如果找到就调用相应的构造函数完成注入,如果在获得实例的时候还需要获取参数的实例,再按照刚才的流程依次注入参数实例

画个简单的流程,如下所示

Component.inject->在Component@L_528_48@module->找到就调用@Provides注解的方法提供实例

​ ->没找到就搜索@Inject注解的构造函数

​ ->都找不到就报错。。。

都没找到肯定就报错了。。。但是会优先寻找Component注册的Module,而@Inject注册的构造器可以调用任何Component的inject方法完成注入,因为@Inject注册的构造器不需要在Component里注册,这里和Module有区别,Module是需在某个Component中注册的,而@Inject不需要

举@L_775_0@mVP中使用Dagger2的示例,我就不贴代码了,直接看下面这个链接好了:http://www.code.net/article/138093.htm

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参学习价值,如果有疑问大家可以留言交流,谢谢大家对编程小技巧的支持

大佬总结

以上是大佬教程为你收集整理的dagger2使用方法教程之简明讲解全部内容,希望文章能够帮你解决dagger2使用方法教程之简明讲解所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。