You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin(Android)如何从Listener的onSuccess()获取返回值并后续使用

Android异步API结果获取最佳实践

你遇到的是异步调用无法同步返回结果的典型问题,REST API请求属于异步操作,不会阻塞外层函数执行,因此外层函数会提前返回空值。以下是两种常用的实现方案:

方案1:回调函数实现

通过传入回调参数的方式,在API请求成功/失败时将结果回传给调用方,适配所有Android开发场景。

改造工具函数

// 入参新增结果回调函数,成功返回签名ID,失败返回异常信息
fun getUserSignatureInfo(context: Context, onResult: (String?, DSRestException?) -> Unit) {
    val eSignApiDelegate = DocuSign.getInstance().getESignApiDelegate()
    val usersApi = eSignApiDelegate.createApiService(UsersApi::class.java)
    val authDelegate = DocuSign.getInstance().getAuthenticationDelegate()
    val user = authDelegate.getLoggedInUser(context)

    eSignApiDelegate.invoke(object : DSESignApiListener {
        override fun <T> onSuccess(response: T?) {
            if (response is UserSignaturesInformation) {
                val userSignature = response.getUserSignatures()[0]
                val signatureId = userSignature.signatureId
                Log.d(TAG, "Signature Id: $signatureId")
                onResult(signatureId, null)
            } else {
                onResult(null, null)
            }
        }

        override fun onError(exception: DSRestException) {
            onResult(null, exception)
        }
    }) {
        usersApi!!.userSignaturesGetUserSignature(user.accountId, user.userId, "signature")
    }
}

Fragment中调用

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    // 可添加加载状态提示优化体验
    showLoading()
    
    getUserSignatureInfo(requireContext()) { signatureId, error ->
        // 切回主线程操作UI
        activity?.runOnUiThread {
            hideLoading()
            when {
                error != null -> {
                    // 处理请求错误,例如弹出提示
                    Toast.makeText(requireContext(), "获取签名信息失败:${error.message}", Toast.LENGTH_SHORT).show()
                }
                signatureId.isNullOrEmpty() -> {
                    Toast.makeText(requireContext(), "未获取到有效签名ID", Toast.LENGTH_SHORT).show()
                }
                else -> {
                    // 拿到结果后初始化适配器
                    recyclerView.adapter = createMyAdapter(signatureId)
                }
            }
        }
    }
}

方案2:Kotlin协程实现(推荐)

将回调式API转换为挂起函数,配合生命周期作用域使用,代码逻辑更简洁,且自动绑定生命周期避免内存泄漏,是现代Android开发的首选方案。

改造为挂起函数

import kotlinx.coroutines.suspendCancellableCoroutine
import kotlin.Result

suspend fun getUserSignatureInfo(context: Context) : Result<String> = suspendCancellableCoroutine { cont ->
    val eSignApiDelegate = DocuSign.getInstance().getESignApiDelegate()
    val usersApi = eSignApiDelegate.createApiService(UsersApi::class.java)
    val authDelegate = DocuSign.getInstance().getAuthenticationDelegate()
    val user = authDelegate.getLoggedInUser(context)

    eSignApiDelegate.invoke(object : DSESignApiListener {
        override fun <T> onSuccess(response: T?) {
            if (response is UserSignaturesInformation) {
                val signatureId = response.getUserSignatures()[0].signatureId
                cont.resume(Result.success(signatureId))
            } else {
                cont.resume(Result.failure(RuntimeException("返回数据格式异常")))
            }
        }

        override fun onError(exception: DSRestException) {
            cont.resume(Result.failure(exception))
        }
    }) {
        usersApi!!.userSignaturesGetUserSignature(user.accountId, user.userId, "signature")
    }
}

Fragment中调用

import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.launch

override fun onActivityCreated(savedInstanceState: Bundle?) {
    super.onActivityCreated(savedInstanceState)
    showLoading()

    lifecycleScope.launch {
        val result = getUserSignatureInfo(requireContext())
        hideLoading()
        result.onSuccess { signatureId ->
            recyclerView.adapter = createMyAdapter(signatureId)
        }.onFailure { error ->
            Toast.makeText(requireContext(), "获取失败:${error.message}", Toast.LENGTH_SHORT).show()
        }
    }
}

注意事项

  • 所有UI相关操作必须在主线程执行,协程的lifecycleScope默认运行在主线程,无需额外切换
  • 建议添加请求过程中的加载状态,避免用户无感知等待
  • 必须覆盖错误处理逻辑,避免网络异常、数据为空等场景导致的崩溃
  • 使用协程方案需要项目已引入Kotlin协程、Android lifecycle相关依赖

内容的提问来源于stack exchange,提问作者Hermann Schwarz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 05:39:00