Как получить контекст внутри объекта? - PullRequest
1 голос
/ 27 июня 2019

Я использую модификацию для получения некоторых данных, и для этого я передаю токен в заголовок для аутентификации. Я хочу получить токен из общих настроек в моем клиентском объекте Retrofit, но не знаю как?

Я пытался получить контекст в объекте, используя функцию, но затем он предупреждает меня, что

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>

}

[ОБНОВЛЕНО] Это моя деятельность, которую я называю модернизацией

  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?

[ОБНОВЛЕНИЕ-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 ]

1 голос
/ 27 июня 2019

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

Также попробуйте прочитать что-нибудь о внедрении зависимостей, 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
1 голос
/ 27 июня 2019

Вместо того, чтобы пытаться сохранить контекст в отдельном файле, сохраните заголовок, который вы хотите отправить. Получите доступ к контексту и общим предпочтениям в своей деятельности.

Изменение:

 RetrofitClient.instance.getContext(this)

На что-то вроде

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