所以我正在开发一个使用 firebase auth 和 dagger hilt 来注入它的项目,一切正常,直到我添加了一些我不知道是什么导致问题的东西,因为我一次添加了多个类和文件并且当我构建时出现此错误:
error: [Dagger/MissingBinding] com.google.firebase.auth.FirebaseAuth cannot be provided without an @Provides-annotated method.
public abstract static class SingletonC implements FragmentGetContextFix.FragmentGetContextFixEntryPoint,
^
A binding for com.google.firebase.auth.FirebaseAuth exists in ...PfeApp_HiltComponents.ViewModelC:
com.google.firebase.auth.FirebaseAuth is injected at
[...PfeApp_HiltComponents.SingletonC] ...model.EmailPasswordAuthRepositoryImpl(auth)
...model.EmailPasswordAuthRepositoryImpl is injected at
[...PfeApp_HiltComponents.ViewModelC] ...views.reset_Password.ResetPasswordViewModel(emailPasswordRepo)
...views.reset_Password.ResetPasswordViewModel is injected at
[...PfeApp_HiltComponents.ViewModelC] ...views.reset_Password.ResetPasswordViewModel_HiltModules.BindsModule.binds(vm)
@dagger.hilt.android.internal.lifecycle.HiltViewModelMap java.util.Map<java.lang.String,javax.inject.Provider<androidx.lifecycle.ViewModel>> is requested at
[...PfeApp_HiltComponents.ViewModelC] dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.ViewModelFactoriesEntryPoint.getHiltViewModelMap() [lr.aym.projet_fin_detudes.PfeApp_HiltComponents.SingletonC ? ...PfeApp_HiltComponents.ActivityRetainedC ? ...PfeApp_HiltComponents.ViewModelC]
(对于三点“...”,我这样做是为了删除包名称,因为它太长了)
基于这里的错误堆栈跟踪是我可以提供的代码:
应用程序模块:
@Module
@InstallIn(ViewModelComponent::class)
class AppModule {
@Provides
fun provideFirebaseAuth()=Firebase.auth
@Provides
fun provideEmailAuthRepository(): EmailPasswordAuthRepository = EmailPasswordAuthRepositoryImpl(
auth = provideFirebaseAuth()
)
@Provides
fun provideFirebaseFirestore()=Firebase.firestore
@Provides
fun provideOneTapClient(
@ApplicationContext
context:Context
)=Identity.getSignInClient(context)
@Provides
@Named("SIGN_IN_REQUEST")
fun provideSignInRequest(
application: Application
)= BeginSignInRequest.builder()
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
.setServerClientId(application.getString(R.string.web_client_id))
.setFilterByAuthorizedAccounts(false)
.build())
.setAutoSelectEnabled(false)
.build()
@Provides
@Named("SIGN_UP_REQUEST")
fun provideSignUpRequest(
application: Application
)= BeginSignInRequest.builder()
.setGoogleIdTokenRequestOptions(
BeginSignInRequest.GoogleIdTokenRequestOptions.builder()
.setSupported(true)
.setServerClientId(application.getString(R.string.web_client_id))
.setFilterByAuthorizedAccounts(false)
.build())
.build()
@Provides
fun provideGoogleSignInOptions(
app: Application
) = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(app.getString(R.string.web_client_id))
.requestEmail()
.build()
@Provides
fun provideGoogleSignInClient(
app: Application,
options: GoogleSignInOptions
) = GoogleSignIn.getClient(app, options)
@Provides
fun provideGoogleAuthRepository(
auth: FirebaseAuth,
oneTapClient: SignInClient,
@Named("SIGN_IN_REQUEST")
signInRequest: BeginSignInRequest,
@Named("SIGN_UP_REQUEST")
signUpRequest: BeginSignInRequest,
db: FirebaseFirestore
): GoogleAuthRepository = GoogleAuthRepositoryImpl(
auth = auth,
oneTapClient = oneTapClient,
signInRequest = signInRequest,
signUpRequest = signUpRequest,
db = db
)
@Provides
fun provideProfileRepository(
auth: FirebaseAuth,
oneTapClient: SignInClient
): ProfileRepository = ProfileRepositoryImpl(
auth = auth,
oneTapClient = oneTapClient,
)
}
emailPasswordAuthImpl:
@Singleton
class EmailPasswordAuthRepositoryImpl @Inject constructor(
private val auth: FirebaseAuth
) : EmailPasswordAuthRepository {
override val currentUser: FirebaseUser?
get() = auth.currentUser
override suspend fun firebaseSignUpWithEmailAndPassword(
email: String,
password: String
): SignUpResponse {
return try {
auth.createUserWithEmailAndPassword(email, password).await()
Log.d("signuptag", "Repo createUser success")
ResponseEmailPassword.Success(true)
} catch (e: Exception) {
Log.d("signuptag", "$e")
ResponseEmailPassword.Failure(e)
}
}
override suspend fun sendEmailVerification(): SendEmailVerificationResponse {
return try {
auth.currentUser?.sendEmailVerification()?.await()
Log.d("signuptag", "SignUp email sent")
ResponseEmailPassword.Success(true)
} catch (e: Exception) {
ResponseEmailPassword.Failure(e)
}
}
override suspend fun firebaseSignInWithEmailAndPassword(
email: String,
password: String
): SignInResponse {
return try {
auth.signInWithEmailAndPassword(email, password).await()
ResponseEmailPassword.Success(true)
} catch (e: Exception) {
ResponseEmailPassword.Failure(e)
}
}
override suspend fun reloadFirebaseUser(): ReloadUserResponse {
return try {
auth.currentUser?.reload()?.await()
Log.d("isEmailVerified", "reloadFirebaseUser: user reloaded ${auth.currentUser?.isEmailVerified}")
ResponseEmailPassword.Success(true)
} catch (e: Exception) {
Log.d("isEmailVerified", "reloadFirebaseUser Failure: ${e}")
ResponseEmailPassword.Failure(e)
}
}
override suspend fun sendPasswordResetEmail(email: String): SendPasswordResetEmailResponse {
return try {
auth.sendPasswordResetEmail(email).await()
ResponseEmailPassword.Success(true)
} catch (e: Exception) {
ResponseEmailPassword.Failure(e)
}
}
override fun signOut() = auth.signOut()
override suspend fun revokeAccess(): RevokeAccessResponse {
return try {
auth.currentUser?.delete()?.await()
ResponseEmailPassword.Success(true)
} catch (e: Exception) {
ResponseEmailPassword.Failure(e)
}
}
override fun getAuthState(viewModelScope: CoroutineScope) = callbackFlow {
val authStateListener = AuthStateListener { auth ->
trySend(auth.currentUser == null)
}
auth.addAuthStateListener(authStateListener)
awaitClose {
auth.removeAuthStateListener(authStateListener)
}
}.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), auth.currentUser == null)
}
重置密码viewModel:
@HiltViewModel
class ResetPasswordViewModel @Inject constructor(
private val emailPasswordRepo: EmailPasswordAuthRepositoryImpl
) : ViewModel() {
var emailValue = mutableStateOf("")
var showLoadingState = mutableStateOf(false)
var resetPasswordResponse by
mutableStateOf<SendPasswordResetEmailResponse>(ResponseEmailPassword.Success(false))
var errorMessage = mutableStateOf("")
fun sendResetPasswordEmail() {
viewModelScope.launch {
resetPasswordResponse=emailPasswordRepo.sendPasswordResetEmail(email = emailValue.value)
}
showLoadingState.value = false
}
}