-
案例一
Car 类是需求依赖方,依赖了 Engine 类;因此我们需要在类变量 Engine 上添加@Inject 来告诉 Dagger2 来为自己提供依赖。 Engine 类是依赖提供方,因此我们需要在它的构造函数上添加@Inject
class Engine { Logger logger = LoggerFactory.getLogger(this.getClass()); /** * Dagger2 通过@Inject注解可以在需要这个类实例的时候来找到这个构造函数并把相关实例构造出来, * * 以此来为被@Inject 标记了的变量提供依赖 * */ @Inject public Engine() { } @NonNull @Override public String toString() { return "Engine{}"; } public void run() { logger.info( "引擎转起来了~~~ "); } }
接下来我们需要创建一个用@Component 标注的接口 CarComponent,这个 CarComponent 其实就是一个注入器,这里用来将 Engine 注入到 Car 中。
@Component interface CarComponent { void inject(Car car); }
完成这些之后我们需要 Build 下项目,让 Dagger2 帮我们生成相关的 Java 类。接着我们就可以在 Car 的构造函数中调用 Dagger2 生成的 DaggerCarComponent 来实现注入(这其实在前面 Car 类的代码中已经有了体现)
public class Car { /** * @Inject:@Inject 有两个作用,一是用来标记需要依赖的变量,以此告诉 Dagger2 为它提供依赖 */ @Inject Engine engine; public Car() { DaggerCarComponent.builder().build().inject(this); } public Engine getEngine() { return this.engine; } public static void main(String... args) { Car car = new Car(); car.getEngine().run(); } }
-
案例二、@Module、@Provide 的使用
如果创建 Engine 的构造函数是带参数的呢?或者 Eggine 类是我们无法修改的呢?这时候就需要@Module 和@Provide 上场了。可以看到下面 Engine 类的代码和上面的入门 demo 中的 Engine 代码几乎一样,只是多了个带参数的构造方法。
class Engine1 { private String name; @Inject Engine1() { } Engine1(String name) { this.name = name; } @Override public String toString() { return "Engine1{" + "name='" + name + '\'' + '}'; } public void run() { System.out.println("引擎转起来了~~~"); } }
接着我们需要一个 Module 类来生成依赖对象。前面介绍的@Module 就是用来标准这个类的,而@Provide 则是用来标注具体提供依赖对象的方法(这里有个不成文的规定,被@Provide 标注的方法命名我们一般以 provide 开头,这并不是强制的但有益于提升代码的可读性)
@Module class MarkCarModule { String engineType; public MarkCarModule(String engineType) { this.engineType = engineType; } @Provides Engine1 provideEngine() { return new Engine1(engineType); } }
接下来我们还需要对 CarComponent 进行一点点修改,之前的@Component 注解是不带参数的,现在我们需要加上 modules = {MarkCarModule.class},用来告诉 Dagger2 提供依赖的是 MarkCarModule 这个类。
@Component(modules = MarkCarModule.class) interface CarComponent1 { void inject(Car1 car1); }
Car 类的构造函数我们也需要修改,相比之前多了个 markCarModule(new MarkCarModule())方法,这就相当于告诉了注入器 DaggerCarComponent 把 MarkCarModule 提供的依赖注入到了 Car 类中。
public class Car1 { @Inject Engine1 engine1; public Car1() { DaggerCarComponent1.builder().markCarModule(new MarkCarModule("国产发动机")).build().inject(this); } public Engine1 getEngine1() { return this.engine1; } public static void main(String... args) { Car1 car = new Car1(); System.out.println(car.getEngine1()); } }Dagger2 的依赖查找顺序说明 我们提到@Inject 和@Module 都可以提供依赖,那如果我们既在构造函数上通过标记@Inject 提供依赖,又通过@Module 提供依赖 Dagger2 会如何选择呢?具体规则如下:
步骤 1:首先查找@Module 标注的类中是否存在提供依赖的方法。
步骤 2:若存在提供依赖的方法,查看该方法是否存在参数。
a:若存在参数,则按从步骤 1 开始依次初始化每个参数;
b:若不存在,则直接初始化该类实例,完成一次依赖注入。
步骤 3:若不存在提供依赖的方法,则查找@Inject 标注的构造函数,看构造函数是否存在参数。
a:若存在参数,则从步骤 1 开始依次初始化每一个参数
b:若不存在,则直接初始化该类实例,完成一次依赖注入。
总结:Dagger2 依赖查找的顺序是先查找 Module 内所有的 @Provides 提供的依赖,如果查找不到再去查找 @Inject 提供的依赖。
-
案例三、@Qualifiers
通过@Qulifier 注解来自定义两个注解,用于区分返回类型相同但又是不同对象的两个具体类
class Engine { private String name; @Inject public Engine() { } public Engine(String name) { this.name = name; } public void run() { System.out.println(name + "启动了"); } } /** * 使用@Qulifier 定义两个注解 */ @Qualifier @Retention(RetentionPolicy.RUNTIME) public @interface QualifierA { } @Qualifier @Retention(RetentionPolicy.RUNTIME) public @interface QualifierB { }同时我们需要对依赖提供方做出修改,用定义的不同的注解来给不同的 provideEngine 方法贴上标签,这样 Dagger2 在寻找同类型对象时,就知道到底应该找哪一个了
@Module public class MarkCarModule { public MarkCarModule() { } @QualifierA @Provides Engine provideEngineA() { return new Engine("国产发动机"); } @QualifierB @Provides Engine provideEngineB() { return new Engine("德国发动机"); } }接下来依赖需求方 Car 类同样需要修改,需要在注入对象前加上自定义的注解便签,以便 Dagger2 知道选择哪个 provide 方法
public class Car { @QualifierA @Inject Engine engineA; @QualifierB @Inject Engine engineB; public Car() { DaggerCarComponent.builder().markCarModule(new MarkCarModule()).build().inject(this); } public Engine getEngineA() { return this.engineA; } public Engine getEngineB() { return this.engineB; } public static void main(String... args) { Car car = new Car(); System.out.println(car.getEngineA()); System.out.println(car.getEngineB()); } }
-
案例4、 @Name 注解
@Name 实际上也是 @Qualifier 注解的一个注解。原理还是 @Qualifier,只不过往上封装了一层使用起来可能更加方便
class Engine { private String name; @Inject public Engine() { } public Engine(String name) { this.name = name; } public void run() { System.out.println(name + "启动了"); } } @Module class MarkCarModule { public MarkCarModule() { } @Provides @Named("A") Engine provideEngineA() { return new Engine("国产发动机"); } @Provides @Named("B") Engine provideEngineB() { return new Engine("德国发动机"); } @Provides @Named("C") Engine provideEngineC() { return new Engine(); } } @Component(modules = MarkCarModule.class) interface CarComponent { void inject(Car car); } public class Car { @Inject @Named("C") Engine engine; public Car() { DaggerCarComponent.create().inject(this); } public Engine getEngine() { return engine; } public static void main(String[] args) { Car car = new Car(); car.getEngine().run(); } }
-
@singleton实现局部单例,是@scope的一个实现类
-
在 Module 对应的 Provides 方法标明@Singleton,表明提供的是一个单例对象。
-
同时在 Component 类标明@Singleton,表明该 Component 中有 Module 使用了@Singleton。
-
public class UserBean { private String name; public UserBean(String name) { this.name = name; } }@Module public class UserModule { @Singleton @Provides UserBean providesUserA() { return new UserBean("Lucas"); } }如果 moudule 所依赖的 Comonent 中有被@Singleton 单例的对象,那么 Conponnent 也必须是单例的@Singleton,表明该 Component 中有 Module 使用了@Singleton
@Component(modules = UserModule.class) @Singleton public interface UserComponent { void inject(MainActivity mainActivity); void inject(SenActivity senActivity); }public class MainActivity extends AppCompatActivity { @Inject UserBean userBeanA; @Inject UserBean userBeanB; @Inject UserBean userBeanC; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DaggerUserComponent.create().inject(this); Logger.addLogAdapter(new AndroidLogAdapter()); Logger.d(userBeanA); Logger.d(userBeanB); Logger.d(userBeanC); } }public class SenActivity extends Activity { @Inject UserBean userBean; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); DaggerUserComponent.create().inject(this); Logger.addLogAdapter(new AndroidLogAdapter()); Logger.d(userBean); } }
-
自定义@scope实现局部单例
@Scope @Documented @Retention(RUNTIME) public @interface UserScope {}public class UserBean { private String name; public UserBean(String name) { this.name = name; } }@Module public class UserModule { @UserScope @Provides UserBean providesUserA() { return new UserBean("Lucas"); } }@Component(modules = UserModule.class) @UserScope public interface UserComponent { void inject(MainActivity mainActivity); void inject(SenActivity senActivity); }public class MainActivity extends AppCompatActivity { @Inject UserBean userBeanA; @Inject UserBean userBeanB; @Inject UserBean userBeanC; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DaggerUserComponent.create().inject(this); Logger.addLogAdapter(new AndroidLogAdapter()); Logger.d(userBeanA); Logger.d(userBeanB); Logger.d(userBeanC); } }public class SenActivity extends Activity { @Inject UserBean userBean; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); DaggerUserComponent.create().inject(this); Logger.addLogAdapter(new AndroidLogAdapter()); Logger.d(userBean); } }
-
全局单例
@Module public class BaseModule { private final Context context; public BaseModule(Context context) { this.context = context; } @Provides @Singleton public SharedPreferences getSharedPreferences() { return context.getSharedPreferences("", Context.MODE_PRIVATE); } }@Component(modules = BaseModule.class) @Singleton public interface BaseComponent { void injectSharedPreferences(MainActivity activity); void injectSharedPreferences(SendActivity activity); }public class App extends Application { BaseComponent baseComponent; @Override public void onCreate() { super.onCreate(); Logger.addLogAdapter(new AndroidLogAdapter()); baseComponent = DaggerBaseComponent.builder().baseModule(new BaseModule(this)).build(); } }public class MainActivity extends AppCompatActivity { @Inject SharedPreferences sf; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ((com.angel.myapplication2.App) getApplication()).baseComponent.injectSharedPreferences(this); Logger.d(sf); } }public class SendActivity extends AppCompatActivity { @Inject SharedPreferences sf; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_send); ((App) getApplication()).baseComponent.injectSharedPreferences(this); Logger.d(sf); } }
8.组件依赖
@Module public class BaseModule { private Context context; public BaseModule(Context context){ this.context =context; } @Singleton @Provides SharedPreferences providesSharedPreferences() { return context.getSharedPreferences("fff", Context.MODE_PRIVATE); } }@Singleton @Component(modules = BaseModule.class) public interface BaseComponent { SharedPreferences getSF(); }public class UserBean { private String name; public UserBean(String name) { this.name = name; } public UserBean() { } }@Module public class UserModule { @UserScope @Provides UserBean providesUserA() { return new UserBean("Lucas"); } }@Component(modules = UserModule.class,dependencies = BaseComponent.class) @UserScope public interface UserComponent { void inject(MainActivity mainActivity); void inject(SenActivity senActivity); }public class App extends Application { private BaseComponent baseComponent; @Override public void onCreate() { super.onCreate(); baseComponent = DaggerBaseComponent.builder().baseModule(new BaseModule(this)).build(); Logger.addLogAdapter(new AndroidLogAdapter()); } public BaseComponent getBaseComponent() { return baseComponent; } }public class MainActivity extends AppCompatActivity { @Inject UserBean userBeanA; @Inject UserBean userBeanB; @Inject UserBean userBeanC; @Inject SharedPreferences sharedPreferences; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DaggerUserComponent.builder().baseComponent(((App) getApplication()).getBaseComponent()).build().inject(this); Logger.d(userBeanA); Logger.d(userBeanB); Logger.d(userBeanC); Logger.d(sharedPreferences); } }public class SenActivity extends Activity { @Inject UserBean userBean; @Inject SharedPreferences sharedPreferences; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); DaggerUserComponent.builder().baseComponent(((App) getApplication()).getBaseComponent()).build().inject(this); Logger.d(userBean); Logger.d(sharedPreferences); }
-
懒加载Lazy<T>,高性能的重要举措之一:在需要的时候才对成员变量进行初始化,可以大幅缩短应用初始化的时间。
使用方法:用 Lazy<T>修饰变量即可。Lazy 是泛型类,接受任何类型的参数。
public class Logger { private String name; public Logger(String name) { this.name = name; } public String getName() { return name; } }
@Module public class LogModule { @Named("aaa") @Singleton @Provides public Logger providerLogger() { return new Logger("aaaa"); } @Named("bbb") @Singleton @Provides public Logger providerLoggerB() { return new Logger("bbbb"); } }
@Singleton @Component(modules = LogModule.class) public interface LogComponent { void inject(MainActivity activity); }
public class MainActivity extends AppCompatActivity { @Inject @Named("aaa") Logger logger; @Inject @Named("bbb") Lazy<Logger> log; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DaggerLogComponent.create().inject(this); com.orhanobut.logger.Logger.addLogAdapter(new AndroidLogAdapter()); com.orhanobut.logger.Logger.d(logger.getName()); com.orhanobut.logger.Logger.d(log.get()); com.orhanobut.logger.Logger.d(log.get().getName()); } }
-
Provider 强制重新加载,我们希望每次都创建一个新的实例,这种情况与 @Singleton 完全相反。
public class Logger { private String name; public Logger(String name) { this.name = name; } public String getName() { return name; } }@Module public class LogModule { @Named("aaa") @Provides public Logger providerLogger() { return new Logger("aaaa"); } @Named("bbb") @Provides public Logger providerLoggerB() { return new Logger("bbbb"); } }@Component(modules = LogModule.class) public interface LogComponent { void inject(MainActivity activity); }public class MainActivity extends AppCompatActivity { @Inject @Named("aaa") Logger logger; @Inject @Named("bbb") Provider<Logger> log; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DaggerLogComponent.create().inject(this); com.orhanobut.logger.Logger.addLogAdapter(new AndroidLogAdapter()); com.orhanobut.logger.Logger.d(logger); com.orhanobut.logger.Logger.d(log.get()); com.orhanobut.logger.Logger.d(log.get()); } }
-
@subComponent
@Module public class BaseModule { private Context context; public BaseModule(Context context){ this.context =context; } @Singleton @Provides SharedPreferences providesSharedPreferences() { return context.getSharedPreferences("fff", Context.MODE_PRIVATE); } }@Singleton @Component(modules = BaseModule.class) public interface BaseComponent { SharedPreferences getSF(); UserComponent provideUserComponent(); }public class UserBean { private String name; public UserBean(String name, SharedPreferences sp) { this.name = name; Logger.d(sp); } }@Module public class UserModule { @Named("A") @UserScope @Provides UserBean providesUserA(SharedPreferences sp) { return new UserBean("Lucas",sp); } @Named("B") @UserScope @Provides UserBean providesUserB(SharedPreferences sp) { return new UserBean("ABC",sp); } }@Subcomponent(modules = UserModule.class) @UserScope public interface UserComponent { void inject(MainActivity mainActivity); }@Scope @Documented @Retention(RUNTIME) public @interface UserScope {}public class App extends Application { @Override public void onCreate() { super.onCreate(); Logger.addLogAdapter(new AndroidLogAdapter()); } }public class MainActivity extends AppCompatActivity { @Named("A") @Inject UserBean userBeanA; @Named("A") @Inject UserBean userBeanB; @Inject @Named("B") UserBean userBeanC; @Inject SharedPreferences sharedPreferences; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DaggerBaseComponent.builder().baseModule(new BaseModule(this)).build() .provideUserComponent().inject(this); Logger.d(userBeanA); Logger.d(userBeanB); Logger.d(userBeanC); Logger.d(sharedPreferences); } }
添加Dagger2依赖
<dependency> <groupId>com.google.dagger</groupId> <artifactId>dagger</artifactId> <version>2.35</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.6.1</version> <configuration> <annotationProcessorPaths> <path> <groupId>com.google.dagger</groupId> <artifactId>dagger-compiler</artifactId> <version>2.35</version> </path> </annotationProcessorPaths> </configuration> </plugin> </plugins> </build>