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

Android项目中CallbackFlow结合Amplify Auth登录时trySend无响应问题排查

问题排查与解决方案

核心排查方向

1. 确认Amplify回调是否被触发

首先要排除Amplify登录操作本身的问题:在Repository的Amplify回调中添加日志,验证登录成功/失败的回调是否真的执行了。

修改Repository代码:

override fun login(username: String, password: String): Flow<DataState<AuthSignInResult>> = callbackFlow {
    try {
        Amplify.Auth.signIn(username, password,
            { result ->
                Log.d("AuthRepo", "登录成功,准备发送结果")
                trySend(DataState.Success(result))
                channel.close()
            },
            { error ->
                Log.d("AuthRepo", "登录失败,准备发送错误")
                trySend(DataState.Failure(error))
                channel.close()
                Log.e("AuthQuickstart", "Failed to sign in", error)
            }
        )

        awaitClose{}

    }catch (e : Exception){
        trySendBlocking(DataState.Failure(e))
        channel.close()
    }
}

如果日志没有输出,说明问题出在Amplify的登录流程(比如配置错误、网络问题或账号密码错误),和CallbackFlow无关,需要先排查Amplify的集成问题。

2. 修复CallbackFlow的发送逻辑

如果回调确实触发了,但collect没有收到数据,问题出在trySend的使用上:

  • trySend是非阻塞发送,默认的CallbackFlow频道缓冲区是RENDEZVOUS(要求发送和接收同步),如果在回调线程发送时,collect端还没准备好,发送会直接失败且无报错。
  • 解决方法有两种:

方法一:使用trySendBlocking替代trySend

trySendBlocking会阻塞当前线程直到发送成功或频道关闭,适合在非协程回调中使用:

// 成功回调
trySendBlocking(DataState.Success(result))
// 失败回调
trySendBlocking(DataState.Failure(error))

方法二:检查trySend的返回值并调整频道缓冲区

保留trySend但添加失败日志,同时给Flow设置缓冲区,避免同步发送限制:

override fun login(username: String, password: String): Flow<DataState<AuthSignInResult>> = callbackFlow {
    try {
        Amplify.Auth.signIn(username, password,
            { result ->
                val sendResult = trySend(DataState.Success(result))
                if (!sendResult.isSuccess) {
                    Log.e("AuthRepo", "发送成功结果失败:${sendResult.exceptionOrNull()}")
                }
                channel.close()
            },
            { error ->
                val sendResult = trySend(DataState.Failure(error))
                if (!sendResult.isSuccess) {
                    Log.e("AuthRepo", "发送失败结果失败:${sendResult.exceptionOrNull()}")
                }
                channel.close()
                Log.e("AuthQuickstart", "Failed to sign in", error)
            }
        )

        awaitClose{}

    }catch (e : Exception){
        trySendBlocking(DataState.Failure(e))
        channel.close()
    }
}.buffer(capacity = Channel.CONFLATED) // 设置缓冲区为CONFLATED,保留最新数据

3. 完善awaitClose的资源清理

虽然不是当前问题的直接原因,但建议在awaitClose中添加Amplify登录请求的取消逻辑,避免内存泄漏:

awaitClose {
    // 如果Amplify支持取消登录请求,在此处调用取消方法
    // 例如:Amplify.Auth.cancelSignIn()(需根据Amplify版本确认API)
}

内容的提问来源于stack exchange,提问作者Mohamed ALI

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 02:20:49