java - 回调获取响应同步 kotlin
问题描述
我试图在同步模式下获得回调的响应,因为所有应用程序都需要响应的值才能工作,没有这个值(令牌)我无法继续使用应用程序。这是我在改造界面中的伴侣对象。我需要在创建客户端之前设置令牌。
我做错了什么?
编辑 :
我在你写的时候写了这个日志:
companion object {
private var mToken: String = ""
fun create(activity: Activity): MyPhoneInterface {
Log.d("tokenMyPhoneInterface", activity.localClassName)
getToken(activity)
Log.d("tokenMyPhoneInterface", "client token $mToken")
val client = OkHttpClient.Builder()
.addInterceptor { chain ->
val request = chain.request().newBuilder()
.addHeader("Authorization", mToken).build()
chain.proceed(request)
}.build()
val retrofit = Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.baseUrl(BuildConfig.API_HOST)
.build()
return retrofit.create(MyPhoneInterface::class.java)
}
private fun getToken(activity: Activity) {
if(!activity.isFinishing && isJwtExpired(mToken)){
val latch = CountDownLatch(1)
(LoginManager(activity)).getToken(true, object : ServiceCallback<String> {
override fun success(token: String) {
Log.d("tokenMyPhoneInterface", "token $token")
mToken = token
latch.countDown()
}
override fun failure(serviceError: ServiceError) {
Log.d("tokenMyPhoneInterface", serviceError.errorMessage)
latch.countDown()
}
})
Log.d("tokenMyPhoneInterface", "before await ")
latch.await()
Log.d("tokenMyPhoneInterface", "after await")
}
}
}
但是我的系统在latch.await()中被阻塞并且日志是:
05-14 18:19:00.127 848-848/com.italy.myphone D/tokenMyPhoneInterface: view.splash.activity.Splash 05-14 18:19:00.131 848-848/com.italy.myphone D/tokenMyPhoneInterface: 之前等待
编辑答案2:
sealed class TokenResult {
class Success(val token: String) : TokenResult()
class Error(val serviceError: ServiceError) : TokenResult()}
suspend fun getToken(activity: Activity): TokenResult {
return suspendCancellableCoroutine { continuation ->
(LoginManager(activity)).getToken(true, object : ServiceCallback<String> {
override fun success(token: String) {
continuation.resume(TokenResult.Success(token))
}
override fun failure(serviceError: ServiceError) {
continuation.resume(TokenResult.Error(serviceError))
}
})
}}
这就是我尝试调用挂起函数的方法:
companion object {
fun create(activity: Activity): MyPhoneInterface{
Log.d("tokenMyPhoneInterface", activity.localClassName)
var token = runBlocking {
return@runBlocking getToken(activity)
}
Log.d("tokenMyPhoneInterface", "obtained token")
Log.d("tokenMyPhoneInterface", "client token $tokenResult")
val client = OkHttpClient.Builder()
.addInterceptor { chain ->
val request = chain.request().newBuilder()
.addHeader("Authorization", "").build()
chain.proceed(request)
}.build()
val retrofit = Retrofit.Builder()
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.client(client)
.baseUrl(BuildConfig.API_HOST)
.build()
return retrofit.create(MyPhoneInterface::class.java)
}
}
那是在接口内部,这是我用来在活动中调用接口/伴随对象的代码:
private val mMyPhoneInterface by lazy {
MyPhoneInterface.create(activity)
}
解决方案
我知道在同步模式下获得回调响应的最好方法是使用协程和函数suspendCancellableCoroutine
在你的情况下,你可以拥有这个函数:
suspend fun getToken(activity: Activity): TokenResult {
return suspendCancellableCoroutine { continuation ->
(LoginManager(activity)).getToken(true, object : ServiceCallback<String> {
override fun success(token: String) {
continuation.resume(TokenResult.Success(token))
}
override fun failure(serviceError: ServiceError) {
continuation.resume(TokenResult.Error(serviceError))
}
})
}
}
sealed class TokenResult {
class Success(val token: String) : TokenResult()
class Error(val serviceError: ServiceError) : TokenResult()
}
在你的activity.onCreate
:
override fun onCreate(savedInstanceState: Bundle?) = runBlocking {
super.onCreate(savedInstanceState)
val tokenResult = getToken(this)
if(tokenResult is Error){
finish()
return@runBlocking
}
//create client here with tokenResult.token value
}
试试看,让我知道...
编辑:在我使用的示例中,runBlocking
因为getToken
是一个挂起函数。在您自己的代码中,您应该在活动之外处理此逻辑。
编辑: 要在您的项目中启用协程,请在您的 gradle 文件中添加以下行:
dependencies {
//other dependencies
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.5"
}
kotlin {
experimental {
coroutines "enable"
}
}
推荐阅读
- javascript - 无法将日期传递给 nivo 折线图
- android - 启用自动旋转时,Android SetRequestRotation 将 Activity 横向翻转为纵向
- vba - 初始化多页用户窗体每一页上的所有控件
- java - 用于测试前置条件的 JAVA 可执行断言
- python - 加入两个具有相同行的 numpy 数组:我得到一个 ValueError
- c# - 如何仅使用属性将对象列表写入文本文件?
- kotlin - 在 Rx java 中将缓存与 concat 运算符集成时出现问题
- mysql - MySQL - 查看半径是否与多边形相交
- laravel - 使用多个数据库时使用哪种目录结构?
- java - 如何编写一个程序来询问多项选择题,然后为每个答案执行输入操作?