匕首缺少与相同类型的数据存储区的绑定 [英] Dagger missing binding with same type of DataStore

查看:36
本文介绍了匕首缺少与相同类型的数据存储区的绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的项目中,我有两个DataStore(SharedPref更好的API)。我有AuthDataStoreUserDataStore,它们有不同的包。我想将这两个数据存储分别注入repositories。我用的是Dagger Hilt

implementation 'com.google.dagger:hilt-android:2.40.5'
    kapt 'com.google.dagger:hilt-android-compiler:2.40.5'
    kapt 'androidx.hilt:hilt-compiler:1.0.0'
    implementation 'androidx.hilt:hilt-navigation-compose:1.0.0'

这是我的DataStoreModule

@Module
@InstallIn(SingletonComponent::class)
object DsModule {

    @Provides
    @Singleton
    fun provideUserDataStoreSource(
        ds: DataStore<Preferences>
    ): UserDataStoreSource {
        return UserDataStoreSourceImpl(ds = ds)
    }

    @Provides
    @Named(value = Constants.USER_DS_NAME)
    @Singleton
    fun provideUserDataStore(
        @ApplicationContext context: Context
    ): DataStore<Preferences> {
        return PreferenceDataStoreFactory.create(
            produceFile = {
                context.preferencesDataStoreFile(Constants.USER_DS_NAME)
            }
        )
    }

    @Provides
    @Singleton
    fun provideAuthDataStoreSource(
        ds: DataStore<Preferences>
    ): AuthDataStore {
        return AuthDataStoreSourceImpl(ds = ds)
    }

    @Provides
    @Named(value = Constants.AUTH_DS_NAME)
    @Singleton
    fun provideAuthDataStore(
        @ApplicationContext context: Context
    ): DataStore<Preferences> {
        return PreferenceDataStoreFactory.create(
            produceFile = {
                context.preferencesDataStoreFile(Constants.AUTH_DS_NAME)
            }
        )
    }
}

这是我的存储库。

open class AuthDataStoreSourceImpl @Inject constructor(
    @Named(value = Constants.AUTH_DS_NAME) private val ds: DataStore<Preferences>
) : AuthDataStore {

    companion object {
        val AUTH_STATE = booleanPreferencesKey("com.galaxytechno.auth_state")
    }

    override suspend fun putAuthFlag(isLoggedIn: Boolean) {
        ds.edit {
            it[AUTH_STATE] = isLoggedIn
        }
    }

    override suspend fun pullAuthFlag(): Flow<Boolean> {
        return ds.data
            .catch { exception ->
                if (exception is IOException) emit(emptyPreferences()) else throw exception

            }.map {
                it[AUTH_STATE] ?: false
            }
    }

}

open class UserDataStoreSourceImpl @Inject constructor(
    @Named(value = Constants.USER_DS_NAME) private val ds: DataStore<Preferences>
) : UserDataStoreSource {

    companion object {
        val ACCESS_TOKEN = stringPreferencesKey("com.galaxytechno.user.access_token")
        val REFRESH_TOKEN = stringPreferencesKey("com.galaxytechno.user.refresh_token")
    }

    override suspend fun putAccessToken(token: String) {
        ds.edit {
            it[ACCESS_TOKEN] = token
        }
    }

    override suspend fun pullAccessToken(): Flow<String> {
        return ds.data
            .catch { exception ->
                if (exception is IOException) emit(emptyPreferences()) else throw exception

            }
            .map {
                it[ACCESS_TOKEN] ?: "empty_access_token"
            }
    } }

以下是我的主要报告:

class AuthRepositoryImpl @Inject constructor(
    private val api: AuthApiService,
    @Named(value = Constants.AUTH_DS_NAME) private val ds: AuthDataStore,
    @Qualifier.Io private val io: CoroutineDispatcher
) : AuthRepository {
    override suspend fun login(
        mobileNumber: String,
        password: String
    ): Flow<RemoteResource<LoginDTO>> {
        return flow {
            emit(
                safeApiCall {
                    api.login(
                        mobileNumber = mobileNumber,
                        password = password
                    )
                }
            )
        }.flowOn(io)
    }

    override suspend fun putAuthFlag(isLoggedIn: Boolean) {
        withContext(io){
            ds.putAuthFlag(isLoggedIn = isLoggedIn)
        }
    }

    override suspend fun pullAuthFlag(): Flow<Boolean> {
        return ds.pullAuthFlag()
    }
}

class UserRepositoryImpl @Inject constructor(
    private val api: UserApiService,
    private val db: UserDatabase,
    @Named(value = Constants.USER_DS_NAME) private val ds : UserDataStoreSource,
    @Qualifier.Io private val io: CoroutineDispatcher
) : UserRepository {

}

这是我的回购模块;

@Module
@InstallIn(SingletonComponent::class)
object RepositoryModule {

    @Provides
    @Singleton
    fun provideUserRepository(
        api: UserApiService,
        db: UserDatabase,
        @Named(value = Constants.USER_DS_NAME) ds : UserDataStoreSource,
        @Qualifier.Io io: CoroutineDispatcher
    ): UserRepository {
        return UserRepositoryImpl(
            api = api,
            db = db,
            ds = ds,
            io = io
        )
    }

    @Provides
    @Singleton
    fun provideAuthRepository(
        api: AuthApiService,
        @Named(value = Constants.AUTH_DS_NAME) ds: AuthDataStore,
        @Qualifier.Io io: CoroutineDispatcher
    ): AuthRepository {
        return AuthRepositoryImpl(
            api = api,
            ds = ds,
            io = io
        )
    }

}

我对此一无所知。我读了很多关于刀柄的文档。但我对匕首缺乏了解。请帮帮我。

我的错误:

D:galaxy_technoChatappuildgeneratedsourcekaptdebugcomgalaxytechnochatappChatApp_HiltComponents.java:140: error: [Dagger/MissingBinding] @javax.inject.Named("auth.chat.ds") com.galaxytechno.chat.auth.data.ds.AuthDataStore cannot be provided without an @Provides-annotated method.
  public abstract static class SingletonC implements ChatApp_GeneratedInjector,
                         ^
      @javax.inject.Named("auth.chat.ds") com.galaxytechno.chat.auth.data.ds.AuthDataStore is injected at
          com.galaxytechno.chat.app.di.RepositoryModule.provideAuthRepository(�, ds, �)
      com.galaxytechno.chat.auth.domain.repository.AuthRepository is injected at
          com.galaxytechno.chat.auth.domain.usecase.GetAuthStateUseCase(repo)
      com.galaxytechno.chat.auth.domain.usecase.GetAuthStateUseCase is injected at
          com.galaxytechno.chat.core.presentation.MainViewModel(getAuthStateUseCase)
      com.galaxytechno.chat.core.presentation.MainViewModel is injected at
          com.galaxytechno.chat.core.presentation.MainViewModel_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
          dagger.hilt.android.internal.lifecycle.HiltViewModelFactory.ViewModelFactoriesEntryPoint.getHiltViewModelMap() [com.galaxytechno.chat.app.ChatApp_HiltComponents.SingletonC ? com.galaxytechno.chat.app.ChatApp_HiltComponents.ActivityRetainedC ? com.galaxytechno.chat.app.ChatApp_HiltComponents.ViewModelC]

推荐答案

根据[Dagger/MissingBinding]行,Dagger正在寻找@Named("auth.chat.ds") AuthDataStore。这意味着您需要精确的绑定匹配,通常使用@Binds@Provides提供,包括完全相同的类名、完全相同的泛型和完全相同的@Named注释(如@Named)。

但是,您的DataStoreModule列出:

@Provides
@Singleton                                  // No @Named annotation
fun provideAuthDataStoreSource(
    ds: DataStore<Preferences>
): AuthDataStore {                          // AuthDataStore
    return /* ... */
}

@Provides
@Named(value = Constants.AUTH_DS_NAME)      // @Named("auth.chat.ds")
@Singleton
fun provideAuthDataStore(
    @ApplicationContext context: Context
): DataStore<Preferences> {                 // DataStore<Preferences>
    return /* ... */
}

因此provideAuthModule@Named(value = Constants.AUTH_DS_NAME) ds: AuthDataStore中的参数不匹配。既不是@Named(AUTH_DS_NAME) DataStore<Preferences>,也不是未命名/不合格的AuthDataStore

取下@Named,您就会好起来:

@Provides
@Singleton
fun provideAuthRepository(
    api: AuthApiService,
    /* @Named(value = Constants.AUTH_DS_NAME) */ ds: AuthDataStore,
    /* ^-------------remove-----------------^ */
    @Qualifier.Io io: CoroutineDispatcher
): AuthRepository

这篇关于匕首缺少与相同类型的数据存储区的绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆