我试图在同步模式下获取回调的响应,因为我的响应值是所有应用程序正常工作所必需的,没有此值( token ),我将无法继续使用该应用程序。
这是我在改造界面内的同伴对象。我需要在创建客户端之前设置 token 。
我做错了什么?
编辑:
我把这写成你写的日志:
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:WAITING之前
编辑答案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))
}
})
}}
这就是我尝试调用suspend函数的方法:
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)
}
}
在接口(interface)内部,这是我用来在 Activity 中调用接口(interface)/伴侣对象的代码:
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
是暂停函数。在您自己的代码中,您应该在 Activity 之外处理此逻辑。编辑:
要在项目中添加协同程序,请在gradle文件中添加以下行:
dependencies {
//other dependencies
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.5"
}
kotlin {
experimental {
coroutines "enable"
}
}