其他
一文吃透Hilt自定义与跨壁垒
https://juejin.cn/user/2066737589654327/posts
创建实例 访问实例 注入依赖 管理生命周期
依赖注入客观需要的入口 系统中存在合理出现的、非DI框架管理的实例,但它不希望破坏其他实例对象的 生命周期 、作用域唯一性,即它的依赖希望交由DI框架管理
使用接口定义 进入点(EntryPoint),并使用 @EntryPoint 注解使其生效; 用 @InstallIn 注解指明访问的Component; 并利用 EntryPoints 完成访问,突破容器壁垒
@InstallIn(UserComponent::class)
interface UserEntryPoint {
fun provideUserVO(): UserVO
}
return EntryPoints.get(
UserComponentManager.instance.generatedComponent(),
UserEntryPoint::class.java
)
}
DI框架需要 创建实例、访问实例、注入依赖、管理生命周期 IOC容器内部也存在着 边界、壁垒,这和它管理实例的机制有关,在Hilt(包括Dagger)中,最大颗粒度的内部壁垒是 Component。
实例之间,也会存在依赖关系; DI框架需要管理内部实例的生命周期; 需要进行依赖注入的客户,本身也存在生命周期,它的依赖对象,应该结合实际需求被合理控制生命周期,避免生命周期泄漏;
ActivityRetainedScoped ActivityRetainedComponent,不受reCreate 影响 ActivityScoped、 ActivityComponent,横竖屏切换等配置变化引起reCreate 开始新生命周期
Activity实例按照 预定Scope对应的生命周期范围 创建、管理Component,访问Component中的实例; Component内的实例可以互相访问,实例的生命周期和Component一致; Activity实例(需要依赖注入的客户)和 Component中的实例 可以访问 父Component中的实例,父Component的生命周期完全包含子Component的生命周期
@Scope
annotation class UserScope
@DefineComponent(parent = SingletonComponent::class)
@UserScope
interface UserComponent {
}
}
import dagger.hilt.DefineComponent
@DefineComponent.Builder
interface Builder {
fun feedUser(@BindsInstance user: User?): Builder
fun build(): UserComponent
}
class UserComponentManager @Inject constructor(
private val builder: UserComponent.Builder
) : GeneratedComponentManager<UserComponent> {
companion object {
lateinit var instance: UserComponentManager
}
private var userComponent = builder
.feedUser(null)
.build()
fun onLogin(user: User) {
userComponent = builder.feedUser(user).build()
}
fun onLogout() {
userComponent = builder.feedUser(null).build()
}
override fun generatedComponent(): UserComponent {
return userComponent
}
}
private val componentCreator: ComponentSupplier
) : GeneratedComponentManager<Any> {
@Volatile
private var component: Any? = null
private val componentLock = Any()
override fun generatedComponent(): Any {
if (component == null) {
synchronized(componentLock) {
if (component == null) {
component = componentCreator.get()
}
}
}
return component!!
}
}
@InstallIn(ActivityRetainedComponent::class)
object AppModule {
@Provides
fun provideUserVO(manager: UserComponentManager):UserVO {
return UserEntryPoint.manualGet(manager.generatedComponent()).provideUserVO()
}
}
场景1:创建独立Library,其中使用Hilt作为DI框架,Library中存在自定义Component,需要初始化管理入口 场景2:项目采用了组件化,该Library按照渠道包需求,渠道包A集成、渠道包B不集成 场景3:项目采用了Uni-App、React-Native等技术,该Library中存在实例由反射方式创建、不受Hilt管理,无法借助Hilt自动注入依赖
即便一个已经编译为aar的库,在被集成后,Hilt依旧能够扫描该库中Hilt相关的内容,进行依赖图聚合 Hilt生成的代码,依旧存在着注解,这些注解可以被注解处理器、字节码工具识别、并进一步处理。可以是Hilt内建的处理器或您自定义的扩展处理器
private val userComponentManager: UserComponentManager
) : Function1<Application, Any> {
override fun invoke(app: Application): Any {
UserComponentManager.instance = userComponentManager
return Unit
}
}
@Module
abstract class AppModuleBinds {
@Binds
@IntoSet
abstract fun provideLibInitializer(bind: LibInitializer): Function1<Application, Any>
}
class App : Application() {
@Inject
lateinit var initializers: Set<@JvmSuppressWildcards Function1<Application, Any>>
override fun onCreate() {
super.onCreate()
initializers.forEach {
it(this)
}
}
}
@InstallIn(SingletonComponent::class)
interface UserComponentEntryPoint {
companion object {
fun manualGet(context: Context): UserComponentEntryPoint {
return EntryPointAccessors.fromApplication(
context, UserComponentEntryPoint::class.java
)
}
}
fun provideBuilder(): UserComponent.Builder
fun provideManager():UserComponentManager
}