android - 如何获取对象内部的上下文?

标签 android kotlin jwt retrofit token

我正在使用 retrofit 来获取一些数据,为此我在 header 中传递了一个 token 以进行身份​​验证。 我想从 Retrofit Client 对象的共享首选项中获取 token ,但我不知道该怎么做?

我试图使用一个函数在对象中获取上下文,但它给了我警告

Do not place Android context classes in static fields (static reference to RetrofitClient which has field context pointing to Context); this is a memory leak (and also breaks Instant Run) less... 

我还尝试在我的改造界面中获取上下文,我在没有警告的情况下获取了上下文,但我不知道从哪里获取共享首选项。

interface Api {
    var context:Context;
    @FormUrlEncoded
    @POST("getMerchantProductsSlideContent")
    fun getProductsForSlide(

 //Don't know how to get value from shared refercne to this header
        @Header("Authentication: Bearer ")

        @Field("token") token:String,
        @Field("deviceId") deviceId:String,
        @Field("content_receiver") content_receiver:String,
        @Field("content_type") content_type:String,
        @Field("data") data:Array<String>
    ):Call<DefaultResponse>

    fun getContext(mContext:Context){
        context = mContext
    }

}

这是retrofitClient.kt

object RetrofitClient {

    private val AUTH = "Bearer $token"
    private const val BASE_URL = "http://192.168.1.5/Projects/Sitapuriya/public/"

    private val okHttpClient = OkHttpClient.Builder()
        .addInterceptor { chain ->
            val original = chain.request()

            val requestBuilder = original.newBuilder()
                .addHeader("Authorization", AUTH)
                .method(original.method(), original.body())

            val request = requestBuilder.build()
            chain.proceed(request)
        }.build()

    val instance: Api by lazy{
        val retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(okHttpClient)
            .build()

        retrofit.create(Api::class.java)
    }
}

这是我改造后的界面

interface Api {
    @FormUrlEncoded
    @POST("getMerchantProductsSlideContent")
    fun getProductsForSlide(

        @Field("token2") token2:String,
        @Field("deviceId") deviceId:String,
        @Field("content_receiver") content_receiver:String,
        @Field("content_type") content_type:String,
        @Field("data") data:Array<String>

    ):Call<DefaultResponse>

}

[更新] 这是我的 Activity n,我称之为改造

  val data = arrayOf(merchantId)
                RetrofitClient.instance.getContext(this)
                RetrofitClient.instance.getProductsForSlide(
                    token,
                    deviceId,
                    "MERCHANT",
                    "MERCHANT_VIEW_BASIC",
                    data
                ).enqueue(object:Callback<DefaultResponse>{

                    override fun onFailure(call: Call<DefaultResponse>, t: Throwable) {
                       Toast.makeText(applicationContext,"ERROR: ${t.message}",Toast.LENGTH_LONG).show()
                    }

                    override fun onResponse(
                        call: Call<DefaultResponse>,
                        response: retrofit2.Response<DefaultResponse>
                    ) {
                        Toast.makeText(applicationContext,"SUCCESS: ${response.body()?.content}",Toast.LENGTH_LONG).show()
                    }

                })

我想从 Shared Preferences 获取 token 并将其用作我的请求的 header ,我知道要访问 Shared Preferences 我们需要一个上下文。如何获取 Object 中的上下文?

[UPDATE-2] 试过@Blundell 的回答

interface Api {
   var token: String
    @FormUrlEncoded
    @POST("getMerchantProductsSlideContent")

    fun getProductsForSlide(
        @Header("Authentication: Bearer $token")
        @Field("token") token:String,
        @Field("deviceId") deviceId:String,
        @Field("content_receiver") content_receiver:String,
        @Field("content_type") content_type:String,
        @Field("data") data:Array<String>
    ):Call<DefaultResponse>

    fun setAuthHeader(token2:String){
        token = token2
    }
}

但它给出错误:An annotation argument must be a compile-time constant

最佳答案

尝试在您的 Activity 中获取 token (您可以使用 Activity 的上下文并从共享首选项中获取 token )并将此 token 传递给您的改造类。

同时尝试阅读一些有关依赖注入(inject)、dagger2、koin 等的内容,以便为您的类提供不同的依赖

interface Api {
    @FormUrlEncoded
    @POST("getMerchantProductsSlideContent")
    fun getProductsForSlide(
        @Header("Authentication") token:String,
        @Field("deviceId") deviceId:String,
        @Field("content_receiver") content_receiver:String,
        @Field("content_type") content_type:String,
        @Field("data") data:Array<String>
    ):Call<DefaultResponse>
}

在您的 Activity 中:

val prefToken = // get it from prefences
val token = "Bearer " + prefToken

关于android - 如何获取对象内部的上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56785889/

相关文章:

android - 获取非常奇怪的长联系人组名称

ios - iOS 的 JWT 认证

c# - 使用 X509Certficate 解密 JWT token 时出现 IDX10659 错误

javascript - JWT Passport 验证

java - Android Studio 无法启动(JDK 而不是 JRE)

android - 什么是 'android.security.MessageDigest' '?

android - 无法从 AsyncTask 获取 Json

android - 辅助应用程序的 FirebaseMessaging.getInstance(firebaseApp) 应该是公共(public)的,但它是私有(private)的?

kotlin - 在同一ViewModel中对LiveData更改使用react

kotlin - Kotlin继承-使用父构造函数创建子实例