Обратный звонок получить ответ Sync kotlin - PullRequest
0 голосов
/ 14 мая 2018

Я пытаюсь получить ответ на обратный вызов в режиме синхронизации, потому что I значение ответа необходимо для работы всего приложения, без этого значения (токена) я не могу продолжать использовать приложение. Это мой сопутствующий объект внутри модифицированного интерфейса. Мне нужно установить токен до создания клиента.

Что я делаю не так?

РЕДАКТИРОВАТЬ:

Я ставлю как этот Логи как ты пишешь:

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

Ответы [ 3 ]

0 голосов
/ 14 мая 2018

Лучший способ получения ответа на обратный вызов в режиме синхронизации - использование сопрограмм и функции 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"
    }
}
0 голосов
/ 18 июня 2018

В конце я использую JavaRx для синхронизации обратного вызова ... это фрагмент.

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()}
0 голосов
/ 14 мая 2018

Вы не должны использовать latch.count. Это равно 1 и latch.count > 1 равно false. Тогда ваша функция возвращается. Просто используйте latch.await(), и он будет ожидать одного из обратных вызовов.

Извините, если я ошибаюсь, у меня недостаточно репо, чтобы комментировать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...