如何在对象内部获取上下文?

时间:2019-06-27 07:16:38

标签: android kotlin jwt retrofit token

我正在使用翻新来获取一些数据,为此,我在身份验证标头中传递了令牌。 我想从Retrofit Client对象中的Shared Preferences中获取令牌,但是我不知道该怎么做?

我尝试使用函数在对象中获取上下文,但随后给我警告

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>

}

[更新]这是我的活动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()
                    }

                })

我想从共享首选项中获取令牌并将其用作我的请求的标头,并且我知道要访问共享首选项,我们需要一个上下文。如何在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
    }
}

但是它给出了错误:注释参数必须是编译时常量

2 个答案:

答案 0 :(得分:1)

而不是尝试将上下文存储在单例中,而是存储要发送的标头。访问活动中的上下文和共享首选项。

更改:

 RetrofitClient.instance.getContext(this)

类似

 RetrofitClient.instance.setAuthHeader(getSharedPreferences().getString("Header"))

答案 1 :(得分:1)

尝试在活动中获取令牌(您可以使用活动的上下文并从共享的首选项中获取令牌),然后将此令牌传递给改造类。

还尝试阅读有关依赖项注入,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>
}

在您的活动中:

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