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
相关产品推荐
相关产品推荐

