【问题标题】:How to pass context inside Retrofit interface如何在 Retrofit 接口中传递上下文
【发布时间】:2021-12-19 18:35:18
【问题描述】:

我想在改造的 HTTP 请求中传递标头授权令牌。令牌保存在 DataStore 中。我的问题是如何从 DataStore 中检索令牌并将其传递给拦截器标头。我花了几个小时思考解决方法并在互联网上搜索,但我一无所获。我也是 Kotlin 的新手。这是代码sn-p:

interface RoomAPIService {

@GET("rooms")
fun getAllRooms(@Header("Authorization")  authHeader: String): Call<List<Room>>
var context: Context


companion object {
    var retrofitService: RoomAPIService? = null
    var token: String = ""
    fun getInstance() : RoomAPIService {

        GlobalScope.launch(Dispatchers.IO)
        {
            //How to pass context to DataRepository.getInstance(context)
          token  = DataStoreRepository.getInstance().getToken().toString()
        }
            val httpClient = OkHttpClient.Builder()
        httpClient.addInterceptor { chain ->
            val request =           chain.request().newBuilder().addHeader("Authorization","Bearer " +  theTokenRetrievedFromDataStore).build()
            chain.proceed(request)
        }
        .
        .
        }
     
        .
        .
         }

这里是DataStoreRepository.kt

class DataStoreRepository(context: Context) {
private val dataStore: DataStore<Preferences> = context.createDataStore(
    name = "token_store"
)

companion object {

    private val TOKEN = preferencesKey<String>("TOKEN")
    private var instance: DataStoreRepository? = null

    fun getInstance(context: Context): DataStoreRepository {
        return instance ?: synchronized(this) {
            instance ?: DataStoreRepository(context).also { instance = it }
        }
    }
}

suspend fun savetoDataStore(token: String) {
   
    dataStore.edit {

        it[TOKEN] = token


    }
}

suspend fun getToken(): String? {
    val preferences: Preferences = dataStore.data.first()
    Log.d("datastore", "token retrieved: ${preferences[TOKEN]} +++++++++++")
    return preferences[TOKEN]
}
}

这里是 MainActivity.kt:

类 MainActivity : AppCompatActivity() {

 private lateinit var  logoutBtn: Button
 private lateinit var bottomNavigation: BottomNavigationView
 private lateinit var binding: ActivityMainBinding
 lateinit var viewModel: RoomViewModel
 private val retrofitService = RoomAPIService.getInstance(this)
 val adapter = RoomsAdapter()
 private var token: String = ""
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)

    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)
    logoutBtn = binding.logoutBtn
    bottomNavigation = binding.bottomNavigation
    viewModel = ViewModelProvider(this, RoomViewModeFactory(RoomRepository(retrofitService))).get(RoomViewModel::class.java)
    binding.recyclerview.adapter = adapter


        var token = intent.getStringExtra("token")
        Log.d("tokenCheck","checkToken: $token")
        if (token != null) {
            viewModel.getAllRooms(token)
        }
        ..

任何帮助将不胜感激!

【问题讨论】:

    标签: android kotlin authorization retrofit2 token


    【解决方案1】:

    您可以更改您的 getInstance() 签名以包含 Context 对象。

    fun getInstance(context:Context) : RoomAPIService {
      GlobalScope.launch(Dispatchers.IO)
        {
           
          token  = DataRepository.getInstance(context).getToken().toString()
        }
    }
    

    【讨论】:

    • 得到这个错误:java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File android.content.Context.getFilesDir()' on an null object reference at android.content.ContextWrapper .getFilesDir
    • 请为 DataStoreRepository 添加代码以了解您的错误。此外,您调用RoomAPIService.getInstance(context) 的那段代码。那里正在传递什么上下文?
    • 我刚刚更新了代码
    • 只有在调用 onCreate 后才能在 Activity 上引用 Context。因此,在您初始化改造服务时,上下文为空。在那里使用延迟初始化。
    【解决方案2】:

    在应用程序的非 UI 模块中使用“上下文”不是一个好习惯。网络模块(或您可能会说的数据层)不应该了解 android 库和组件。我的建议是在“变量”中使用一个值,该值可以在运行时更改并且可以在 Network 模块中看到,然后在 OkHttp 拦截器中使用它。最后,您只需要在应用程序的开头初始化变量即可。

    【讨论】:

    • "可以在运行时更改,可以在 Network 模块中看到,然后在 OkHttp 拦截器中使用" 你能详细说明一下吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-18
    • 2018-12-28
    • 2016-08-31
    • 2014-12-16
    • 1970-01-01
    相关资源
    最近更新 更多