安卓SharedPreferences提交慢导致跳转MapsActivity读取不到值如何解决
问题根源
你遇到的问题核心不是SharedPreferences写入速度慢,而是两个异步任务并行执行导致的时序错误:
makeHttpRequest()是Volley实现的异步网络请求,firebaseSignUp()是Firebase的异步认证请求,二者同时触发时没有执行顺序保证,大概率会出现Firebase认证先完成、直接跳转页面,但Volley请求还没返回、还没执行parseHtml()方法存储name和nurseId的情况,导致MapsActivity读取不到完整参数。- 即使你尝试用
commit()同步写入SP,只要两个异步任务的执行顺序错了,依然会出现读取失败的问题。
解决方案
第一步:调整异步任务执行顺序
必须等Volley网络请求完成、成功写入name和nurseId到SP之后,再触发Firebase的认证绑定逻辑,不要同时发起两个请求。
修改点击事件代码,移除并行调用的firebaseSignUp():
signInButton.setOnClickListener(v -> { if (validateFields()) if (checkInternet()){ progressBar.setVisibility(View.VISIBLE); // 增加加载状态避免重复点击 makeHttpRequest(); } });
修改Volley请求成功回调,确认Volley请求成功后再调用Firebase认证:
response -> { if (parseHtml(response)) { progressBar.setVisibility(View.GONE); // Volley请求完成,已存储name和nurseId,再触发Firebase绑定 firebaseSignUp(); } else { progressBar.setVisibility(View.GONE); notAMemberTextView.setVisibility(View.VISIBLE); notAMemberTextView.setText(R.string.you_are_not_a_member); } }
第二步:确保SP写入完成后再跳转
Firebase认证成功后,使用commit()同步写入SP,确认写入成功后再执行页面跳转:
public void firebaseSignUp() { AuthCredential credential = EmailAuthProvider.getCredential(email, password); try { Objects.requireNonNull(firebaseAuth.getCurrentUser()).linkWithCredential(credential). addOnSuccessListener(authResult -> { editor.putString("email", email); editor.putString("password", password); // commit是同步操作,会阻塞直到SP写入完成,返回值代表写入是否成功 boolean isSaved = editor.commit(); if (isSaved) { startActivity(new Intent(NewNurseActivity.this, MapsActivity.class)); finish(); } else { Toast.makeText(getApplicationContext(), "数据保存失败,请重试", Toast.LENGTH_LONG).show(); } }).addOnFailureListener(e -> { Log.e("sign_in_error", e.getMessage()); Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_LONG).show(); }); } catch (NullPointerException ignored){} }
额外优化建议
不要将密码明文存储在SharedPreferences中,存在严重的安全泄露风险,上线前请替换为加密存储方案,比如Jetpack Security提供的EncryptedSharedPreferences。
内容的提问来源于stack exchange,提问作者Ahmed Gamal
相关产品推荐
相关产品推荐

