Как добавить модернизированную базовую аутентификацию в сетевой модуль с рукоятью кинжала?

Я новичок в Котлине и использую рукоять кинжала для чистого кода.

Мне нужна базовая аутентификация во всех моих запросах, кроме запроса на вход, потому что токен поступает из. запрос на вход.

Мой вопрос в том, как я могу выполнить все свои запросы, кроме входа в систему, используя базовую аутентификацию с рукояткой кинжала?

Мой объект модуля выглядит так:

Любой совет или образец кода, пожалуйста:)

@Module
@InstallIn(ApplicationComponent::class)
object NetworkingModule {

    @Provides
    fun providesBaseUrl(): String {
        return NetworkingConstants.BASE_URL
    }

    @Provides
    fun providesLoggingInterceptor(): HttpLoggingInterceptor {
        return HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
    }

    @Provides
    fun provideOkHttpClient(loggingInterceptor: HttpLoggingInterceptor): OkHttpClient {
        val okHttpClient = OkHttpClient().newBuilder()

        okHttpClient.callTimeout(40, TimeUnit.SECONDS)
        okHttpClient.connectTimeout(40, TimeUnit.SECONDS)
        okHttpClient.readTimeout(40, TimeUnit.SECONDS)
        okHttpClient.writeTimeout(40, TimeUnit.SECONDS)
        okHttpClient.addInterceptor(loggingInterceptor)
        okHttpClient.build()
        return okHttpClient.build()
    }

    @Provides
    fun provideConverterFactory(): Converter.Factory {
        return GsonConverterFactory.create()
    }

    @Provides
    fun provideRetrofitClient(okHttpClient: OkHttpClient, baseUrl: String, converterFactory: Converter.Factory): Retrofit {
        return Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient)
            .addConverterFactory(converterFactory)
            .build()
    }

    @Provides
    fun provideRestApiService(retrofit: Retrofit): ApiService {
        return retrofit.create(ApiService::class.java)
    }
}

Я думаю, мне следует использовать BasicAuthInterceptor, но как я могу добавить это в модуль рукоятки?

1 ответ

Если вам нужно добавить еще один перехватчик для некоторых других запросов, это означает, что вам нужно предоставить разные реализации (несколько привязок) одного и того же типа.

Чтобы сообщить Hilt, как предоставлять разные реализации (несколько привязок) одного и того же типа, вы можете использовать квалификаторы.

Квалификатор - это аннотация, используемая для идентификации привязки. Если вам нужно добавить еще один перехватчик, реализовав интерфейс Intercepor, вы можете использовать аннотацию @Binds для функции внутри модуля Hilt.Но... вам нужно создать еще один модуль для использования @Binds.

Модули Hilt не могут содержать как нестатические, так и абстрактные методы привязки, поэтому вы не можете размещать аннотации @Binds и @Provides в одном классе.

Итак, ваш код должен быть примерно таким:

// ПЕРВЫЙ: определите четыре квалификатора в NetworkingModule для двух типов OkHttpClient и двух разных retrofitClient:

        @Module
        @InstallIn(ApplicationComponent::class)
        object NetworkingModule {
            //FIRST: define four qualifiers in the NetworkingMoule
            @Qualifier  // define qualifier for LoginRetrofitClient
            @Retention(AnnotationRetention.BINARY)
            annotation class LoginRetrofitClient
    
            @Qualifier // define qualifier for OtherRetrofitClient
            @Retention(AnnotationRetention.BINARY)
            annotation class OtherRetrofitClient
    
            @Qualifier  // define qualifier for LoginOkHttpClient
            @Retention(AnnotationRetention.BINARY)
            annotation class LoginOkHttpClient
    
            @Qualifier // define qualifier for OtherOkHttpClient
            @Retention(AnnotationRetention.BINARY)
            annotation class OtherOkHttpClient
    
    
            @Provides
            fun providesBaseUrl(): String {
            return NetworkingConstants.BASE_URL
            }
    
            // make sure add qualifier for LoginRetrofitClient
            @LoggingInterceptor
            @Provides
            fun providesLoggingInterceptor(): HttpLoggingInterceptor {
            return HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY)
            }
    
            // add @LoginOkHttpClient for providerOkHttpClient which we add AuthBasicInterceptorto to
            @LoginOkHttpClient
            @Provides
            fun provideOkHttpClient(authBasicInterceptor: AuthBasicInterceptor): OkHttpClient {
            val okHttpClient = OkHttpClient().newBuilder()
    
            okHttpClient.callTimeout(40, TimeUnit.SECONDS)
            okHttpClient.connectTimeout(40, TimeUnit.SECONDS)
            okHttpClient.readTimeout(40, TimeUnit.SECONDS)
            okHttpClient.writeTimeout(40, TimeUnit.SECONDS)
            okHttpClient.addInterceptor(authBasicInterceptor)
            okHttpClient.build()
            return okHttpClient.build()
            }
    
            // add @OtherOkHttpClient for providerOkHttpClient which we add loggingInterceptor to
            @OtherOkHttpClient
            @Provides
            fun provideOkHttpClient(loggingInterceptor: HttpLoggingInterceptor): OkHttpClient {
            val okHttpClient = OkHttpClient().newBuilder()
    
            okHttpClient.callTimeout(40, TimeUnit.SECONDS)
            okHttpClient.connectTimeout(40, TimeUnit.SECONDS)
            okHttpClient.readTimeout(40, TimeUnit.SECONDS)
            okHttpClient.writeTimeout(40, TimeUnit.SECONDS)
            okHttpClient.addInterceptor(loggingInterceptor)
            okHttpClient.build()
            return okHttpClient.build()
            }
    
            @Provides
            fun provideConverterFactory(): Converter.Factory {
            return GsonConverterFactory.create()
            }
    
            // make sure add qualifier for LoginRetrofitClient
            @LoginRetrofitClient
            @Provides
            fun provideRetrofitClient(@LoginOkHttpClient okHttpClient: OkHttpClient,  // Remember to add @LoginOkHttpClient qualifier to distinguish OkHttpClient dependencies
            baseUrl: String, converterFactory: Converter.Factory): Retrofit {
            return Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient)
            .addConverterFactory(converterFactory)
            .build()
            }
    
    
            @OtherRetrofitClient
            @Provides
            fun provideRetrofitClient(@OtherOkHttpClient okHttpClient: OkHttpClient, // Remember to add @OtherOkHttpClient qualifier to distinguish OkHttpClient dependencies
            baseUrl: String,
            converterFactory: Converter.Factory): Retrofit {
            return Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(okHttpClient)
            .addConverterFactory(converterFactory)
            .build()
            }
    
           // also you need different flavors of ApiService by defining two more qualifiers for different retrofitClients which I commented that for simplicity
           // @Provides
            //fun provideRestApiService(retrofit: Retrofit): ApiService {
           // return retrofit.create(ApiService::class.java)
           // }
    
    
            }

Теперь нам нужно добавить AuthBasicInterceptor, который нам нужен для создания нового модуля с именем AuthInterceptorModule.kt и добавления к нему абстрактной функции bindAuthInterceptor типа Interceptor.

AuthInterceptorModule.kt

    
    @InstallIn(ApplicationComponent::class)
      @Module
      abstract class AuthInterceptorModule {
    
            @Binds
            abstract fun bindAuthInterceptor(basicAuthInterceptor: AuthBasicInterceptor): Interceptor
            }

и Создайте еще один класс с именем AuthBasicInterceptor.kt, реализующий Interceptor:

            class AuthBasicInterceptor @Inject constructor() : Interceptor {
            ...
            }
    

Все, все настроено. Теперь вы можете вводить retrofitClients в другие классы, например:

        @AndroidEntryPoint
        class MainActivity : AppCompatActivity() {

        @LoginRetrofitClient
        @Inject lateinit var loginRetrofit: Retrofit

        @OtherRetrofitClient
        @Inject lateinit var otherRetrofit: Retrofit

        override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

       ...
        }

        ...
        }
Другие вопросы по тегам