Как получить контекст внутри объекта?

Я использую модификацию для получения некоторых данных, и для этого я передаю токен в заголовке для аутентификации. Я хочу получить токен из общих настроек в моем клиентском объекте 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
    }
}

Но выдает ошибку: Аргумент аннотации должен быть константой времени компиляции.

Где код, где вы вызываете метод getProductsForSlide? вы можете получить доступ к SharePreferences там

Blundell 27.06.2019 09:30

вам лучше использовать dagger2 или добавить перехватчик или передать заголовок через параметры

Raj 27.06.2019 09:37

проверьте проект, он вам поможет. github.com/zigic88/Dagger2-модернизация

Raj 27.06.2019 09:40

Если вы хотите получить данные из Shared, то, не внося серьезных изменений в свой код, вы можете просто получить их, расширив статический метод класса приложения, чтобы получить контекст, а затем создать объект sharedpreferences.

Hari N Jha 27.06.2019 09:46

@Blundell Пожалуйста, проверьте обновленный вопрос

Pratham Vaidya 27.06.2019 09:47

Хорошо попробую так сделать

Pratham Vaidya 27.06.2019 09:52
1
6
1 941
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Изменять:

 RetrofitClient.instance.getContext(this)

Что-то вроде

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

Сэр, я попробовал ваш ответ, но он дал мне ошибку. Пожалуйста, проверьте мой обновленный вопрос (ОБНОВЛЕНИЕ-2)

Pratham Vaidya 27.06.2019 14:06
Ответ принят как подходящий

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

Также попробуйте прочитать что-нибудь о внедрении зависимостей, 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

Да, я могу получить токен внутри своей деятельности, но я точно не знаю, как передать его в классе модернизации. Я пытался что-то передать токен, см. мой обновленный вопрос (ОБНОВЛЕНИЕ-2)

Pratham Vaidya 27.06.2019 14:09

@PrathamVaidya попробуй это

shmakova 27.06.2019 14:23

Спасибо, ваше решение сработало, я впервые использую модификацию.

Pratham Vaidya 27.06.2019 14:42

Другие вопросы по теме

Похожие вопросы

Создайте библиотеку зависимостей gradle с включением транзитивных зависимостей
Запутался в обработке ошибок на сетевом уровне при реализации MVVM в Android. Как уведомить пользователя о том, что что-то не так?
Предложите пользователям обновить приложение Android с помощью Google Play (поддержка Google In-App Update)
Firebase – получение URL-адреса изображения
Как переключиться с одного фрагмента на другой при нажатии на элемент списка?
Очистить теги OneSignal, когда пользователь удаляет приложение
Как настроить представление, когда пользователь нажимает кнопку «Назад» телефона, он возвращается к представлению в том же классе Java
Отправлять данные на сервер каждую минуту (для проверки статуса пользователя)
Не удается найти версию «androidx.annotation:annotation», которая удовлетворяет ограничениям версии: ошибка при запуске androidTests
Модернизация методов onResponse и onFailure не вызывается