Android接入AWS Amplify出现OkHttp Dispatcher空指针导致数据备份失败
问题根因定位
- Amplify初始化时序错误:当前代码在Amplify未完成初始化时就调用了
fetchAuthSession和后续API操作,Amplify内部依赖的OkHttp客户端尚未实例化,直接触发Dispatcher空指针异常 - API查询未做空校验:
queryNotes方法直接遍历response.data,接口返回异常、无权限或无数据时response.data为null,遍历操作直接触发空指针,也会导致查询结果为空 - AWS权限配置缺失:当前登录的Cognito用户未分配后端数据源(DynamoDB/S3)的访问权限,接口返回无权限结果,被Amplify内部处理为空数据
- OkHttp版本冲突:项目依赖的OkHttp版本和Amplify内部依赖的版本不兼容,导致Dispatcher实例化失败
修复方案
1. 修复Amplify初始化时序
调整代码逻辑,等收到Amplify初始化成功的Hub回调后再执行会话拉取和后续操作:
fun initialize(applicationContext: Context): Backend { try { Amplify.addPlugin(AWSCognitoAuthPlugin()) Amplify.addPlugin(AWSApiPlugin()) Amplify.addPlugin(AWSS3StoragePlugin()) Amplify.configure(applicationContext) Log.i(TAG, "Initialized Amplify") } catch (e: AmplifyException) { Log.e(TAG, "Could not initialize Amplify", e) return this } Log.i(TAG, "Registering hub event") Amplify.Hub.subscribe(HubChannel.AUTH) { hubEvent: HubEvent<*> -> when (hubEvent.name) { InitializationStatus.SUCCEEDED.toString() -> { Log.i(TAG, "Amplify successfully initialized") // 初始化完成后再拉取会话状态 fetchAuthSession() } InitializationStatus.FAILED.toString() -> { Log.i(TAG, "Amplify initialization failed") } // 原有其他回调逻辑保持不变 else -> { when (AuthChannelEventName.valueOf(hubEvent.name)) { AuthChannelEventName.SIGNED_IN -> { updateUserData(true) Log.i(TAG, "Hub: Signed_in") } AuthChannelEventName.SIGNED_OUT -> { updateUserData(false) Log.i(TAG, "Hub: Signed out") } else -> Log.i(TAG, """HUB EVENT :${hubEvent.name}""") } } } } return this } // 将会话拉取逻辑抽为单独方法,初始化完成后再调用 private fun fetchAuthSession() { Log.i(TAG, "Retrieving session status") Amplify.Auth.fetchAuthSession( { result -> Log.i(TAG, result.toString()) val cognitoAuthSession = result as AWSCognitoAuthSession this.updateUserData(cognitoAuthSession.isSignedIn) when (cognitoAuthSession.identityId.type) { AuthSessionResult.Type.SUCCESS -> Log.i(TAG, "IdentityId : " + cognitoAuthSession.identityId.value) AuthSessionResult.Type.FAILURE -> Log.i(TAG, "IdentityId not present because: " + cognitoAuthSession.identityId.error.toString()) } }, { error -> Log.i(TAG, error.toString()) } ) }
2. 修复查询方法的空指针和批量刷新问题
添加非空校验,批量处理查询结果避免多次UI刷新:
fun queryNotes() { Log.i(TAG, "Querying notes") Amplify.API.query( ModelQuery.list(NoteData::class.java), { response -> Log.e(TAG, "Queried") // 先判断接口返回错误 if (response.hasErrors()) { Log.e(TAG, "Query error: ${response.errors.first().message}") return@query } // 非空判断后批量处理数据 response.data?.let { data -> val noteList = data.map { UserData.Note.from(it) } UserData.addNotes(noteList) // 需在UserData中新增批量添加方法,仅触发一次UI刷新 } ?: run { Log.w(TAG, "Query return empty data") UserData.resetNotes() } }, { error -> Log.e(TAG, "Query failure", error) } ) }
3. 修复权限和版本冲突问题
- 检查AWS控制台Cognito身份池的已认证用户角色,添加对应DynamoDB表、S3存储桶的读写权限
- 在Module级别的build.gradle中添加强制OkHttp版本配置,避免版本冲突:
configurations.all { resolutionStrategy { force "com.squareup.okhttp3:okhttp:4.10.0" force "com.squareup.okhttp3:logging-interceptor:4.10.0" } }
4. 空查询结果额外排查点
如果修复后仍返回空结果,确认:
- 调用
createNote后收到了成功回调,数据已实际写入AWS后端 - 查询时登录的用户和创建笔记的用户为同一账号,Amplify默认会添加所有者过滤,跨账号无法查询到私有数据
内容的提问来源于stack exchange,提问作者Burcu
相关产品推荐
相关产品推荐

