如何在Kotlin中使用Retrofit获得响应头?



你好,我正在使用retrofit和rxjava2异步工作

和我必须从头部得到的值,而与服务器开发人员交谈。

然而,我不知道如何从我使用的方法获得标题。我知道如何从Call Response中获取它,但我不知道如何带来header,因为使用的方法不同。

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}")
})
)

我目前的情况如下。我需要登录后服务器返回的头,我可以从okhttp日志中看到它,但我不知道如何获得特定的头

要检索响应头和其他有用的信息,您可以使用retrofit2包中的Response类型。要使用此方法,请将登录方法的返回类型更改为Single<retrofit2.Response<UserResponse>>

@POST("user")
fun login( @Body loginRequest : LoginRequest): Single<retrofit2.Response<UserResponse>>

现在在ViewModel

中检索标题
addDisposable(
model.loginBody(loginRequest)
.subscribeOn(Schedulers.io())
.subscribe({
val headers = it.headers() // do something with headers
val data = it.body()
_loginResult.postValue(data)
}, {
Timber.d("response error, message : ${it.localizedMessage}")
})
)

建议而非解决方案

不是解决问题的问题,而是即使很晚了,因为你使用Kotlin,更好的解决方案是从rxJava迁移到Kotlin Flow。它允许你使用suspend函数来做你的改造调用,然后使用Kotlin Flow在IO线程上做rxJava的工作。

它还允许您以更简单的方式使用Response<T>改装对象。

例子:

改造请求

@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))
}
}

DataState:

DataState是一个密封类,允许区分发出的状态
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>()
}

如何调用Kotlin流以在IO线程上启动它以防止阻塞Main(或UI)线程

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
*/
}
}

相关内容

  • 没有找到相关文章

最新更新