Ale*_*don 2 java android asynchronous callback 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")
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是我的系统在闩锁.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))
}
})
}}
Run Code Online (Sandbox Code Playgroud)
这就是我尝试调用挂起函数的方法:
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)
}
}
Run Code Online (Sandbox Code Playgroud)
这是在一个接口内,这是我用来在活动中调用接口/伴随对象的代码:
private val mMyPhoneInterface by lazy {
MyPhoneInterface.create(activity)
}
Run Code Online (Sandbox Code Playgroud)
我知道在同步模式下获得回调响应的最好方法是使用协程和函数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()
}
Run Code Online (Sandbox Code Playgroud)
而在你的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
}
Run Code Online (Sandbox Code Playgroud)
试一试,让我知道...
编辑:在我使用的示例中,runBlocking因为getToken是一个挂起函数。在您自己的代码中,您应该在活动之外处理此逻辑。
编辑: 要在您的项目中启用协程,请在您的 gradle 文件中添加以下几行:
dependencies {
//other dependencies
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.5"
}
kotlin {
experimental {
coroutines "enable"
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4193 次 |
| 最近记录: |