Hello I am working on async using retrofit and rxjava2
and I have to get the value from the header while talking to the server developer.
However, I don't know how to get the header from the method I use. I know how to get it from Call Response, but I don't know how to bring the header because the method used is different.
my retrofit2 class
private val retrofit: Retrofit = Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(client())
.baseUrl(serverIp)
.build()
val userApi: UserAPI = retrofit.create(UserAPI::class.java)
my model class
@POST("user")
fun login(
@Body loginRequest : LoginRequest
) : Single<UserResponse>
data class LoginRequest(
val phone: String?,
@SerializedName("gender")
val gender: String?,
@SerializedName("age")
val age: String?,
@SerializedName("email")
val email: String?
)
data class UserResponse (
override var status: Int,
override var message: String,
override var timestamp: String,
var data: Data
) : CommonResponse() {
data class Data(
var username: String?,
var token: String?
)
}
my viewModel ( rx )
addDisposable(
model.loginBody(loginRequest)
.subscribeOn(Schedulers.io())
.subscribe({
_loginResult.postValue(it)
}, {
Timber.d("response error, message : ${it.localizedMessage}")
})
)
My current situation is as follows. I need the headers returned by the server after login, I can see it from the okhttp log, but I don't know how to get a specific header
Not a question of solving your problem but even if it's late, as you're
using Kotlin, a better solution would be to migrate from rxJava to Kotlin Flow. It allows you to use suspend
functions to do your retrofit calls, then use Kotlin Flow to do the rxJava's job on the IO thread.
It also allows you to use the Response<T>
retrofit object in a simpler way.
@POST(YOUR_ROAD) // Retrofit road
suspend fun connect(
@Body credentials: CredentialsObjectBody
): Response<ConnectionObjectResponse>
// The function is suspending the thread with suspend keyword
suspend fun yourFunction(): Flow<DataState<TypeForEmitter>> = flow {
try {
body.clientId = sessionPrefs.deviceName!!
val connectionResponse =
majorApi.connect(
// what you need to put in the body
)
.apply {
if (isSuccessful) {
body()?.let {
// Here you can use what's in the request body
emit(DataState.Success(it))
} ?: throw Exception("Request body was null")
} else {
throw Exception(headers()["message"]) // use throw to handle the error in the catch
}
}
} catch (e: Exception) {
Log.e(TAG, "error: ${e.message}")
emit(DataState.Error(e))
}
}
sealed class DataState<out R> {
data class Success<out T>(val data: T) : DataState<T>()
data class Error(val exception: Exception) : DataState<Nothing>()
object Loading : DataState<Nothing>()
}
withContext(Dispatchers.IO) {
yourFunction().onEach {
/*
onEach is like onNext, but emits every type of error, compared to rxJava
that differentiates next/success, complete and error events
*/
}
}