关于java:回调获取响应同步kotlin

Callback get response Sync kotlin

我正试图在同步模式下获取回调的响应,因为我的响应值是所有应用程序正常工作所必需的,没有此值(令牌),我将无法继续使用该应用程序。
这是我在改造界面内的同伴对象。我需要在创建客户端之前设置令牌。

我做错了什么?

编辑:

我在撰写本文时将其作为日志:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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函数的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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)
    }
}

在接口内部,这是我用来在活动中调用接口/伴生对象的代码:

1
2
3
    private val mMyPhoneInterface by lazy {
    MyPhoneInterface.create(activity)
}

我知道在同步模式下获取回调响应的最好方法是使用
协程和函数suspendCancellableCoroutine
在您的情况下,您可以具有以下功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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中:

1
2
3
4
5
6
7
8
9
10
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文件中添加以下行:

1
2
3
4
5
6
7
8
9
dependencies {
//other dependencies
    implementation"org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.5"
}
kotlin {
    experimental {
        coroutines"enable"
    }
}


最后,我使用JavaRx来同步回调。这是代码段。

1
2
3
4
5
6
7
8
9
10
11
12
13
fun getToken(loginManager: LoginManager): String {
return Single
        .create(SingleOnSubscribe<String> { emitter ->
            loginManager.getToken(object : TokenSimpleCallback {
                override fun onSuccess(token: String) {
                    emitter.onSuccess(token)
                }

                override fun onFailure(loginServiceError: LoginServiceError) {
                    emitter.onError(Throwable(loginServiceError.toString()))
                }
            })
        }).blockingGet()}

您不应该使用latch.count。它等于1,latch.count > 1false。然后返回您的函数。只需使用latch.await(),它将等待回调之一。

对不起,如果我错了,我没有足够的存储库可以发表评论。