Dagger Hilt 能否感知 Module class 中的变量是否发生变化并更新其值?
Can Dagger Hilt realise whether a variable in a Module class has changed and update its value?
我正在编写一个使用 Firebase Auth 和 DI 的 Android 应用程序。
在这个应用程序中,我经常需要使用用户的 UID 来执行一些数据库操作,为了寻找停止通过 MVVM 层传递 UID 的方法,我决定尝试依赖注入。
我的 AppModule 如下所示:
AppModule.kt
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Singleton
@Provides
fun provideServer(@ApplicationContext c: Context) = Server(c, Volley.newRequestQueue(c), provideUid())
@Singleton
@Provides
fun provideFirebase() = FirebaseSource(FirebaseAuth.getInstance())
@Singleton
@Provides
fun provideFirebaseAuth() = Firebase.auth
@Singleton
@Provides
fun provideFirebaseUser(): Boolean {
return provideFirebaseAuth().currentUser != null
}
@Singleton
@Provides
// FIXME
fun provideUid(): String {
return provideFirebaseAuth().currentUser?.uid ?: ""
}
}
Function provideUid()
returns Firebase 当前用户的 UID,并作为依赖项注入到单独的 Server
class:
Server.kt(部分)
class Server @Inject constructor(
private val c: Context,
private val volleyRequestQueue: RequestQueue,
private val uid: String
): IServer {
应用首次启动时,Dagger Hilt 使用此构造函数并提供空 UID,因为此时没有登录用户。此行为在应用程序生命周期的其余部分持续存在,并且 Server
class 永远不会有非空 UID,因为它已经使用空 UID 构造为 属性.
重新启动应用程序将构建具有非空 UID 的 Server
class,因为 Firebase Auth 会保留一些用户身份验证状态的注册表。
那么我的问题是,Dagger Hilt 是否可以意识到 UID 已更改并更新其值。
我尝试过的事情:
- 正在从
provideUid()
中删除 @Singleton
注释
- 正在将
Server
的 uid
参数从 val
更改为 var
。
你可以试试:
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
fun provideServer(@ApplicationContext c: Context, queue: RequestQueue, uid: String) = Server(c, queue, uid)
@Provides
@Singleton
fun provideResponseQueue(@ApplicationContext c: Context) = Volley.newRequestQueue(c)
@Singleton
@Provides
fun provideFirebase() = FirebaseSource(FirebaseAuth.getInstance())
@Singleton
@Provides
fun provideFirebaseAuth() = Firebase.auth
@Singleton
@Provides
fun provideFirebaseUser(): Boolean {
return provideFirebaseAuth().currentUser != null
}
@Provides
// FIXME
fun provideUid(): String {
return provideFirebaseAuth().currentUser?.uid ?: ""
}
}
如果在应用程序中创建了一次服务器对象的实例,则此解决方案将不起作用。
首先,您很少希望一个 @Provides
方法调用另一个方法。通常最好让 Dagger 为您连接这些方法之间的依赖关系。
Dagger 永远不会重新创建或更新它已经创建的对象。如果您想要一个始终 return 当前 uid 的引用,您可以直接注入 FirebaseAuth
或 Provider<String>
.
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
// Consider making a @Singleton @Provides method for RequestQueue.
// That would let you use the @Inject annotation on Server's constructor.
@Singleton
@Provides
fun provideServer(
@ApplicationContext c: Context,
uidProvider: Provider<String>
) = Server(c, Volley.newRequestQueue(c), uidProvider)
@Singleton
@Provides
fun provideFirebase() = FirebaseSource(FirebaseAuth.getInstance())
@Singleton
@Provides
fun provideFirebaseAuth() = Firebase.auth
@Provides
fun provideFirebaseUser(auth: FirebaseAuth): Boolean {
return auth.currentUser != null
}
// This should not be a singleton.
// Consider using @Named or a custom qualifier for common types like String.
@Provides
fun provideUid(auth: FirebaseAuth): String {
return auth.currentUser?.uid ?: ""
}
}
Can Dagger Hilt realize whether a variable in a Module class has changed and then update its value?
最简单的答案是否定的,不能。
要让 Dagger Hilt 为 FirebaseAuth 提供实例,您只能使用:
@Provides
fun provideFirebaseAuth() = FirebaseAuth.getInstance()
如果你想在另一个方法中使用上面的实例,正如@Nitrodon 已经指出的那样,你应该将该实例作为参数传递给下一个方法并且 not 调用它直接地。所以代码应该是这样的:
@Provides
fun provideFirebaseUser(auth: FirebaseAuth) = auth.currentUser
但是,这没有用,因为根据用户的身份验证状态,currentUser
对象可以为 null。除此之外,当一个对象被创建时,你可以使用它但它不会被重新创建。所以在你的 AppModule class 中添加它没有任何意义。您应该做的是在您的应用程序代码中注入一个 FirebaseAuth 实例,并检查 currentUser
是否为空。如果它不为空,那么您可以安全地使用 UID。
如果您想知道身份验证状态,那么您应该附加一个 AuthStateListener,正如我在以下 post:
的回答中所解释的那样
我正在编写一个使用 Firebase Auth 和 DI 的 Android 应用程序。
在这个应用程序中,我经常需要使用用户的 UID 来执行一些数据库操作,为了寻找停止通过 MVVM 层传递 UID 的方法,我决定尝试依赖注入。
我的 AppModule 如下所示:
AppModule.kt
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Singleton
@Provides
fun provideServer(@ApplicationContext c: Context) = Server(c, Volley.newRequestQueue(c), provideUid())
@Singleton
@Provides
fun provideFirebase() = FirebaseSource(FirebaseAuth.getInstance())
@Singleton
@Provides
fun provideFirebaseAuth() = Firebase.auth
@Singleton
@Provides
fun provideFirebaseUser(): Boolean {
return provideFirebaseAuth().currentUser != null
}
@Singleton
@Provides
// FIXME
fun provideUid(): String {
return provideFirebaseAuth().currentUser?.uid ?: ""
}
}
Function provideUid()
returns Firebase 当前用户的 UID,并作为依赖项注入到单独的 Server
class:
Server.kt(部分)
class Server @Inject constructor(
private val c: Context,
private val volleyRequestQueue: RequestQueue,
private val uid: String
): IServer {
应用首次启动时,Dagger Hilt 使用此构造函数并提供空 UID,因为此时没有登录用户。此行为在应用程序生命周期的其余部分持续存在,并且 Server
class 永远不会有非空 UID,因为它已经使用空 UID 构造为 属性.
重新启动应用程序将构建具有非空 UID 的 Server
class,因为 Firebase Auth 会保留一些用户身份验证状态的注册表。
那么我的问题是,Dagger Hilt 是否可以意识到 UID 已更改并更新其值。
我尝试过的事情:
- 正在从
provideUid()
中删除 - 正在将
Server
的uid
参数从val
更改为var
。
@Singleton
注释
你可以试试:
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
@Provides
fun provideServer(@ApplicationContext c: Context, queue: RequestQueue, uid: String) = Server(c, queue, uid)
@Provides
@Singleton
fun provideResponseQueue(@ApplicationContext c: Context) = Volley.newRequestQueue(c)
@Singleton
@Provides
fun provideFirebase() = FirebaseSource(FirebaseAuth.getInstance())
@Singleton
@Provides
fun provideFirebaseAuth() = Firebase.auth
@Singleton
@Provides
fun provideFirebaseUser(): Boolean {
return provideFirebaseAuth().currentUser != null
}
@Provides
// FIXME
fun provideUid(): String {
return provideFirebaseAuth().currentUser?.uid ?: ""
}
}
如果在应用程序中创建了一次服务器对象的实例,则此解决方案将不起作用。
首先,您很少希望一个 @Provides
方法调用另一个方法。通常最好让 Dagger 为您连接这些方法之间的依赖关系。
Dagger 永远不会重新创建或更新它已经创建的对象。如果您想要一个始终 return 当前 uid 的引用,您可以直接注入 FirebaseAuth
或 Provider<String>
.
@Module
@InstallIn(SingletonComponent::class)
object AppModule {
// Consider making a @Singleton @Provides method for RequestQueue.
// That would let you use the @Inject annotation on Server's constructor.
@Singleton
@Provides
fun provideServer(
@ApplicationContext c: Context,
uidProvider: Provider<String>
) = Server(c, Volley.newRequestQueue(c), uidProvider)
@Singleton
@Provides
fun provideFirebase() = FirebaseSource(FirebaseAuth.getInstance())
@Singleton
@Provides
fun provideFirebaseAuth() = Firebase.auth
@Provides
fun provideFirebaseUser(auth: FirebaseAuth): Boolean {
return auth.currentUser != null
}
// This should not be a singleton.
// Consider using @Named or a custom qualifier for common types like String.
@Provides
fun provideUid(auth: FirebaseAuth): String {
return auth.currentUser?.uid ?: ""
}
}
Can Dagger Hilt realize whether a variable in a Module class has changed and then update its value?
最简单的答案是否定的,不能。
要让 Dagger Hilt 为 FirebaseAuth 提供实例,您只能使用:
@Provides
fun provideFirebaseAuth() = FirebaseAuth.getInstance()
如果你想在另一个方法中使用上面的实例,正如@Nitrodon 已经指出的那样,你应该将该实例作为参数传递给下一个方法并且 not 调用它直接地。所以代码应该是这样的:
@Provides
fun provideFirebaseUser(auth: FirebaseAuth) = auth.currentUser
但是,这没有用,因为根据用户的身份验证状态,currentUser
对象可以为 null。除此之外,当一个对象被创建时,你可以使用它但它不会被重新创建。所以在你的 AppModule class 中添加它没有任何意义。您应该做的是在您的应用程序代码中注入一个 FirebaseAuth 实例,并检查 currentUser
是否为空。如果它不为空,那么您可以安全地使用 UID。
如果您想知道身份验证状态,那么您应该附加一个 AuthStateListener,正如我在以下 post:
的回答中所解释的那样