2024年HarmonyOS鸿蒙最新基于Dagger2(1),阿里的面试官

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

前言

这里主要针对@MapKey、@Scope、@Qualifier注解还有@IntoSet,@IntoMap和@ElementsIntoSet的理解,因为这几个注解是贯穿始终的,和其他注解或多或少存在关联,如果不提前讲解,后面关联上无法更好的理解。

@MapKey、@Scope、@Qualifier三个注解仅仅可用于修饰注解。MapKey是Dagger2自定义的,Scope和Qualifier是javax.inject下的注解。

这里包括后面的章节中注解的先后顺序都是经过我精挑细选的,务必保证后面说到的注解关联的注解先被说到。

那个啥,为什么还是那么…咳咳,如同作者的发型那么柔顺!!!

@Scope

我们直译过来表示范围,这个注解是用于修饰注解的注解。

@Scope修饰的注解具体使用规则

  1. 节点使用@Scope修饰的注解最多只允许出现一个;
  2. 使用@Module或@ProducerModule修饰的module节点不允许使用Scope修饰的注解修饰;
  3. 绑定方法bindingMethod节点(module节点中的方法,使用@Provides 、@Produces 、@Binds 、@Multibinds、@BindsOptionalOf修饰)。其中@Provides和@Binds修饰的方法允许同时使用@Scope修饰的注解修饰,@Produces、@Multibinds和@BindsOptionalOf修饰的方法不允许同时使用@Scope修饰的注解修饰;
  4. @Inject或@AssistedInject修饰的构造函数不允许使用同时使用@Scope修饰的注解修饰;并且@AssistedInject修饰的构造函数所在的父级节点不允许使用使用@Scope修饰的注解修饰,但是使用@Inject修饰的构造函数所在父级节点允许使用@Scope修饰的注解修饰;
  5. @BindsInstance修饰的方法或方法参数不允许同时使用@Scope修饰;

Scope表示一个作用域,表示当前Scope修饰的注解修饰的节点所属的currentcomponent节点及其往下的subcomponent节点都可以使用该节点,我们以@Singleton为例:

Module节点,里面包含Subcomponent1,Subcomponent2,Subcomponent3几个subcomponent节点,Component节点中关联Module节点,Component节点的入口方法inject的作用是实例化MembersInjector类:

@Module(subcomponents = Subcomponent1.class,Subcomponent2.class,Subcomponent3.class)
public class Module{
	@Provides
	@Singleton
	public A bindingMethod(B b){
		return new A(b);
	}
}

@Component(modules = Module.class)
public calss Component{
	inject(MembersInjector m);

	public SubcomponentX getSubcomponentX();//这个也是一个Subcomponent节点
}


public class MembersInjector{
	
	@Inject
	public C C;
}


@Singleton
public class C {
	

	@Inject
	public C(){}
} 

已上面的实例解说如下:

  1. 当前@Singleton和@Provides修饰的bindingMethod方法返回的A的实例化既可以在当前Component作用域中使用,也可以在Subcomponent1,Subcomponent2,Subcomponent3和SubcomponentX(当然了,仅限于Subcompoonent中的实例化需要的A实例化对象的情况下)使用;
  2. 当前@Singleton修饰的C类(因为MembersInjector类是待实例化的对象,所以对象中@Inject修饰的变量类型(或普通方法返回类型))实例化既可以在当前Component作用域中使用也可以在Subcomponent1,Subcomponent2,Subcomponent3和SubcomponentX中使用;
  3. 那如果在Subcomponent1中定义了@Singleton修饰的节点,那么该节点的实例对象是不能再父级fathercomponent中使用的。

为什么有好几种@Scope修饰的注解,有什么不同?

Dagger当前2.38.1版本中源码中有几个Scope修饰的注解,@Reusable、@PerGeneratedFile、@PerComponentImplementation、@ProductionScope;还有javax.inject包下有一个@Singleton;

  1. @Reusable:@Reusable和@Binds同时修饰一个module节点中的bindingMethod方法,那么当前bindingMethod方法参数类型A节点如果没有使用@Scope修饰的注解,那么直接使用SingleCheck;如果A节点使用了@Scope修饰的注解,那么使用DoubleCheck;
  • SingleCheck和DoubleCheck的区别,SingleCheck单例获取A对象;DoubleCheck不仅仅获取A对象,并且校验当前A对象的实例化始终都是同一个实例;
 @Binds
     @Reusable
         // to avoid parsing options more than once
     CompilerOptions bindCompilerOptions(
             ProcessingEnvironmentCompilerOptions processingEnvironmentCompilerOptions
     ); 

  • 如上代码案例,ProcessingEnvironmentCompilerOptions如果没有使用@Scope修饰的注解修饰,那么是SingleCheck单例,否则是DoubleCheck双重校验(单例 + 校验必须同一实例),其实对我们来说好像并没有多大影响;
  1. @Reusable其他情况和@Singleton用法都是在作用域中DoubleCheck双重校验;
  2. @PerGeneratedFile表示将当前修饰的节点及其往下关联的节点和当前所属的currentcomponent生成的代码写在同一个文件中,没有实际意义;
  3. @PerComponentImplementation:Dagger内部处理代码,相当于一个A类,但是这个A可能包含自己,那么我们将另外开辟一个用于生成子类A的实例,需要用到@PerComponentImplementation;
  4. @ProductionScope:如果使用了@ProductionComponent或@ProductionSubcomponent修饰的component节点,那么Dagger为我们生成一个@Module修饰的module节点,该module节点中有monitor方法:
 @Provides
 @ProductionScope
 static ProductionComponentMonitor monitor(Provider<component节点类型> component,Provider<Set<ProductionComponentMonitor.Factory>> factories){
 	return Monitors.createMonitorForComponent(component, factories);
 } 

* ProductionScope实际作用还是当前component的作用域,这里使用monitor方法的目的在于整个@ProductionComponent或@ProductionSubcomponent修饰的component节点的监控。

@Qualifier

直译过来是预选的意思。@Qualifier修饰的注解使用规则如下

  1. 节点上只允许出现一个@Qualifier修饰注解的注解;
  2. componentMethod方法只有在返回类型是subcomponent节点或subcomponent.creator节点情况下才允许使用Qualifier修饰的注解修饰;
  3. bindingMethod方法可以被Qualifier修饰的注解修饰;
  4. 被Inject或AssistedInject修饰的构造方法不允许使用Qualifier修饰的注解修饰,但是构造函数的参数可以;
  5. @Assisted修饰的参数节点不能被Qualifier注解修饰的注解修饰;
  6. MembersInjector的成员注入T类型不允许使用Qualifier修饰的注解修饰;
  7. 一个节点允许使用Qualifier修饰,那么当前节点类型(如果是方法,则表示方法返回类型)的构造函数允许使用AssistedInject修饰。

@Qualifier修饰的注解主要是为了实例化过程中成功匹配到正确的参数,我们以案例说话:

@Retention(RUNTIME)
@Qualifier
public @interface ProcessingOptions {}

public final class ExternalBindingGraphPlugins {

	    @Inject
ExternalBindingGraphPlugins(...,
        @ProcessingOptions Map<String, String> processingOptions) {
	}
}

@Module
interface ProcessingEnvironmentModule{
    @Provides
    @ProcessingOptions
    static Map<String, String> processingOptions(XProcessingEnv xProcessingEnv) {
        return xProcessingEnv.getOptions();
    }

	@Provides
	static Map<String, String> getMap(String str) {
        return new Map<String,String>();
    }
} 

如上图所示,ExternalBindingGraphPlugins对象的实例化需要 Map<String, String> 对象,这里有两个Map<String,String>,那么需要靠@ProcessingOptions精确匹配。

  • 在容易产生类型混淆的情况下会用到@Qualifier修饰的注解,这个也非常容易理解。

@IntoSet、@IntoMap和@ElementsIntoSet

** @IntoSet、@IntoMap和@ElementsIntoSet用于修饰方法,规则如下**:

  1. 不允许同时使用,一个方法上仅仅可以使用前@IntoSet、@IntoMap和@ElementsIntoSet中的一个;
  2. 必须在bindingMethod绑定方法上使用,并且只支持@Provides、@Produces或@Binds三种类型的bindingMethod方法;
  3. 如果使用了@ElementsIntoSet,那么当前bindingMethod方法返回类型必须是Set< T>;
  4. @IntoMap 和@MapKey修饰的注解一定是成对出现的;
@IntoSet

收集同一种类型对象,下面给个案例了解下:

@Module
public interface BindingMethodValidatorsModule {

    //下面的都是该方法参数
    @Provides
    static ImmutableMap<ClassName, BindingMethodValidator> indexValidators(
            Set<BindingMethodValidator> validators) {
        return uniqueIndex(validators, BindingMethodValidator::methodAnnotation);
    }

    @Binds
    @IntoSet
    BindingMethodValidator provides(ProvidesMethodValidator validator);

    @Binds
    @IntoSet
    BindingMethodValidator produces(ProducesMethodValidator validator);

    @Binds
    @IntoSet
    BindingMethodValidator binds(BindsMethodValidator validator);

    @Binds
    @IntoSet
    BindingMethodValidator multibinds(MultibindsMethodValidator validator);

    @Binds
    @IntoSet
    BindingMethodValidator bindsOptionalOf(BindsOptionalOfMethodValidator validator);
} 

  • @Binds修饰的bindingMethod方法有且仅有一个参数,并且参数类型一定是方法返回类型或返回类型子类。

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

Jpa-1715635646587)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 18
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值