kotlin 如果< androidx.datastore.preferences.core.Preferences>没有@ Provides注解的方法,则无法提供androidx.datastore.core.DataStore

yh2wf1be  于 2023-01-17  发布在  Kotlin
关注(0)|答案(1)|浏览(185)

我不知道这个错误,我只是在github仓库的代码下面的人,我只是想存储和提供一个数据存储保存令牌和入站状态。请有人帮助我这个错误。

数据存储模块

import android.content.Context
import androidx.datastore.preferences.preferencesDataStore
import com.seinoindomobil.dev.epod.data.local.datastore.DataStorePreferenceStorage
import com.seinoindomobil.dev.epod.data.local.datastore.DataStorePreferenceStorage.Companion.PREFS_NAME
import com.seinoindomobil.dev.epod.data.local.datastore.PreferenceStorage
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent

    @Module
    @InstallIn(SingletonComponent::class)
    object LocalModule {
    
       private val Context.datastore by preferencesDataStore(PREFS_NAME)
    
        @Provides
        fun provideDataStore(@ApplicationContext context: Context): PreferenceStorage = DataStorePreferenceStorage(context.datastore)
    
    }

存储库模块

import com.seinoindomobil.dev.epod.data.local.datastore.PreferenceStorage
import com.seinoindomobil.dev.epod.data.remote.LoginApi
import com.seinoindomobil.dev.epod.data.remote.repository.LoginRepositoryImpl
import com.seinoindomobil.dev.epod.data.remote.repository.OnBoardingRepositoryImpl
import com.seinoindomobil.dev.epod.domain.repository.LoginRepository
import com.seinoindomobil.dev.epod.domain.repository.OnBoardingRepository
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

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

    @Provides
    @Singleton
    fun provideLoginRepository(
        api: LoginApi,
        preferenceStorage: PreferenceStorage
    ): LoginRepository {
        return LoginRepositoryImpl(api, preferenceStorage)
    }

    @Provides
    @Singleton
    fun provideOnBoardingRepository(preferenceStorage: PreferenceStorage): OnBoardingRepository {
        return OnBoardingRepositoryImpl(preferenceStorage)
    }
}

数据存储接口

interface PreferenceStorage {
    suspend fun setOnboardingState(isCompleted :Boolean)
    val getOnboardState :Flow<Boolean>

    suspend fun setUserToken(token:String)
    val getUserToken :Flow<String>
    suspend fun deleteToken()

}

数据存储首选项

class DataStorePreferenceStorage @Inject constructor(
    private val dataStore: DataStore<Preferences>
) : PreferenceStorage {

    object PreferenceKeys {
        val IS_ONBOARD_COMPLETED = booleanPreferencesKey("IS_ONBOARD_COMPLETED")
        val USER_TOKEN = stringPreferencesKey("user_token")
    }

    companion object {
        const val PREFS_NAME = "my_datastore"
    }

    override suspend fun setOnboardingState(isCompleted: Boolean) {
        dataStore.setValue {
            it[PreferenceKeys.IS_ONBOARD_COMPLETED] = isCompleted
        }
    }

    override val getOnboardState: Flow<Boolean>
        get() = dataStore.getValue {
            it[PreferenceKeys.IS_ONBOARD_COMPLETED] ?: false
        }

    override suspend fun setUserToken(token: String) {
       dataStore.setValue {
           it[PreferenceKeys.USER_TOKEN] = token
       }
    }

    override val getUserToken: Flow<String>
        get() = dataStore.getValue {
            it[PreferenceKeys.USER_TOKEN] ?: ""
        }

    override suspend fun deleteToken() {
        dataStore.setValue {
            it.remove(USER_TOKEN)
        }
    }
}

身份验证拦截器

class AuthInterceptor @Inject constructor(
    private val tokenManager: DataStorePreferenceStorage,
): Interceptor {
    override fun intercept(chain: Interceptor.Chain): Response {
        val token = runBlocking {
            tokenManager.getUserToken.first()
        }
        val request = chain.request().newBuilder()
        request.addHeader("Authorization", "Bearer $token")
        return chain.proceed(request.build())
    }
}

作者验证者

class AuthAuthenticator @Inject constructor (
    private val tokenManager: DataStorePreferenceStorage,
): Authenticator {

    override fun authenticate(route: Route?, response: Response): Request? {
        val token = runBlocking {
            tokenManager.getUserToken.first()
        }
        return runBlocking {
            val newToken = getNewToken(token)

            if (!newToken.isSuccessful || newToken.body() == null) { //Couldn't refresh the token, so restart the login process
                tokenManager.deleteToken()
            }

            newToken.body()?.let {
                tokenManager.setUserToken(it.result.signature?.access_token.toString())
                response.request.newBuilder()
                    .header("Authorization", "Bearer ${it.result.signature?.access_token}")
                    .build()
            }
        }
    }

    private suspend fun getNewToken(refreshToken: String?): retrofit2.Response<LoginDTO> {
        val loggingInterceptor = HttpLoggingInterceptor()
        loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
        val okHttpClient = OkHttpClient.Builder().addInterceptor(loggingInterceptor).build()

        val retrofit = Retrofit.Builder()
            .baseUrl("http://192.168.203.64:5555/authenticate/")
            .addConverterFactory(GsonConverterFactory.create())
            .client(okHttpClient)
            .build()
        val service = retrofit.create(LoginApi::class.java)
        return service.refreshToken("Bearer $refreshToken")
    }
}
mutmk8jj

mutmk8jj1#

@Provides
 fun provideDataStore(@ApplicationContext context: Context): PreferenceStorage = DataStorePreferenceStorage(context.datastore)

应该有一个@Singleton符号。而且,这个函数是为了提供一个DataStore<Preferences>示例。

@Provides
 @Singleton
 fun provideDataStore(@ApplicationContext context: Context): DataStore<Preferences>{
    // Return an instance of DataStore<Preferences>
 }

对于注入PreferenceStorage方法,您可以在单独的模块中定义如下函数:-

@Binds
abstract fun providePreferenceStorage(pref : DataStorePreference) : PreferenceStorage

由于datastore示例是被注入的,因此不需要将其作为参数传递。

相关问题