Я использую модификацию для получения некоторых данных, и для этого я передаю токен в заголовке для аутентификации. Я хочу получить токен из общих настроек в моем клиентском объекте 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
}
}
Но выдает ошибку: Аргумент аннотации должен быть константой времени компиляции.
вам лучше использовать dagger2 или добавить перехватчик или передать заголовок через параметры
проверьте проект, он вам поможет. github.com/zigic88/Dagger2-модернизация
Если вы хотите получить данные из Shared, то, не внося серьезных изменений в свой код, вы можете просто получить их, расширив статический метод класса приложения, чтобы получить контекст, а затем создать объект sharedpreferences.
@Blundell Пожалуйста, проверьте обновленный вопрос
Хорошо попробую так сделать
Вместо того, чтобы пытаться сохранить контекст в синглтоне, сохраните заголовок, который вы хотите отправить. Получите доступ к контексту и общим настройкам в своей деятельности.
Изменять:
RetrofitClient.instance.getContext(this)
Что-то вроде
RetrofitClient.instance.setAuthHeader(getSharedPreferences().getString("Header"))
Сэр, я попробовал ваш ответ, но он дал мне ошибку. Пожалуйста, проверьте мой обновленный вопрос (ОБНОВЛЕНИЕ-2)
Попробуйте получить токен в своей деятельности (вы можете использовать контекст активности и получить токен из общих настроек) и передать этот токен в свой класс модернизации.
Также попробуйте прочитать что-нибудь о внедрении зависимостей, 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)
@PrathamVaidya попробуй это
Спасибо, ваше решение сработало, я впервые использую модификацию.
Где код, где вы вызываете метод
getProductsForSlide? вы можете получить доступ к SharePreferences там