android - Koin + Retrofit 在运行时添加标题

标签 android kotlin retrofit2 interceptor koin

我在 MVVM 架构中有一个基于硬币和改造的项目。我想在注册此项目后在运行时使用“viewmodel”打印数据并在标题中添加“token”的值。 但是我无法提供获取我保存在 SharedPreferences 中的 token 所需的上下文结构。我怎样才能以最干净的形式处理它?<​​/p>

 fun createNetworkClient(baseUrl: String) =
        retrofitClient(baseUrl, httpClient())


    private fun httpClient(): OkHttpClient {

        val httpLoggingInterceptor = HttpLoggingInterceptor(HttpLoggingInterceptor.Logger.DEFAULT)
        val clientBuilder = OkHttpClient.Builder()
        if (BuildConfig.DEBUG) {
            httpLoggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
            clientBuilder.addInterceptor(httpLoggingInterceptor)
        }
        clientBuilder.addInterceptor { chain ->
            val newRequest = chain.request().newBuilder()
                .addHeader( //I can't get token because there is no context here.
                    "Authorization", "Bearer ${PreferencesHelper.getInstance(context).token.toString()}"
                )
                .build()
            chain.proceed(newRequest)
        }



        clientBuilder.readTimeout(120, TimeUnit.SECONDS)
        clientBuilder.writeTimeout(120, TimeUnit.SECONDS)
        return clientBuilder.build()
    }

    private fun retrofitClient(baseUrl: String, httpClient: OkHttpClient): Retrofit =
        Retrofit.Builder()
            .baseUrl(baseUrl)
            .client(httpClient)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()

应用模块

val appModule = module {
    single {
        androidApplication().getSharedPreferences("PREFERENCES", android.content.Context.MODE_PRIVATE)
    }
    single { createNetworkClient(BuildConfig.BASE_URL) }
    single { (get() as Retrofit).create(Api::class.java) } 
    viewModel {
        ContactViewModel(get())
    }
}

我的联系 Activity

 private val contactList: ContactViewModel  by viewModel()
    override fun onCreate(savedInstanceState: Bundle?) {
        viewModel = contactList

        super.onCreate(savedInstanceState)
        binding.adapter = ContactAdapter(this)
        binding.layoutManager = LinearLayoutManager(this)

        contactList.getContactList()

        contactList.contactListLiveData.observe(this, Observer { list ->
            if (list != null)
                binding.adapter?.update(list)
        })
    }

最佳答案

您可以创建一个 Koin 模块来提供共享首选项:

val sharedPreferencesModule = module {

   single {
      androidApplication().getSharedPreferences("PREFERENCES",  android.content.Context.MODE_PRIVATE)
   }
}

然后用Koin注入(inject)到生成Retrofit客户端的类中。

编辑

您需要修改您的createNetworkClient 方法签名:

fun createNetworkClient(baseUrl: String, preferences: SharedPreferences)

然后用 Koin 注入(inject)它:

val appModule = module {
    single {
        androidApplication().getSharedPreferences("PREFERENCES", android.content.Context.MODE_PRIVATE)
    }
    single { createNetworkClient(BuildConfig.BASE_URL, get()) }

    ...
}

然后您将收到在 createNetworkClient 方法中注入(inject)的共享首选项,只需实现从共享首选项中检索 token 的逻辑即可。

关于android - Koin + Retrofit 在运行时添加标题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56808706/

相关文章:

java - Dagger 2 : Multiple entries with same key

java - 在 Android 中使用 Retrofit 时带有动态键的 JSON

java - 改造更改 URL

android - 使用 AlarmManager 设置重复通知 - Android

android - 背景图像并不总是居中

java - 安卓图标电池

Android:搜索栏更改仅由用户检测

java - 如何在 Android 中创建文本字段以在 Flutter 应用程序中使用

android - 类型不匹配 : inferred type is Context? 但需要上下文 - Kotlin

java - 我无法在 onReceive() 中的 onResponse() 之外使用 json 结果 - 改造