Android开发中如何处理Firebase异步特性 解决onDataChange晚于update执行问题
问题根因
Firebase 数据库读取属于异步操作,onDataChange() 会在网络请求返回数据后才会回调执行,而你的更新按钮初始化后默认可点击,若用户在数据加载完成前点击触发update(),就会出现全局变量name、mail未赋值的异常,同时原有代码的变更判断逻辑本身也存在空指针风险。
可直接复用的修改方案
你只需对现有代码做3处调整即可解决问题:
- 页面初始化时先禁用更新按钮,等
onDataChange()执行完成、数据加载完毕后再放开按钮点击权限 - 在
onDataChange()中同步给全局变量name、mail赋值,保证变更判断的基准值正确 - 修正
isNamechanged()、isEmailchanged()的判断逻辑,避免空指针异常
修改后的完整代码
public class Profile extends AppCompatActivity { private FirebaseUser user; private DatabaseReference reference; private String userID; EditText Username,email; String name,mail; Button button; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_profile); Username=findViewById(R.id.Username1); email=findViewById(R.id.emailadress); button=findViewById(R.id.editinfo); // 初始化时先禁用按钮,防止数据加载完成前被点击 button.setEnabled(false); user= FirebaseAuth.getInstance().getCurrentUser(); reference= FirebaseDatabase.getInstance().getReference("Users"); userID=user.getUid(); reference.child("Driver").child(userID).addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(@NonNull DataSnapshot snapshot) { Users usersnapshot=snapshot.getValue(Users.class); if(usersnapshot!=null){ String username=usersnapshot.getUsername(); String Email=usersnapshot.getMail(); Username.setText(username); email.setText(Email); // 给全局变量赋值,作为变更判断的基准 name = username; mail = Email; // 数据加载完成,放开按钮点击权限 button.setEnabled(true); } } @Override public void onCancelled(@NonNull DatabaseError error) { // 加载失败也可以自定义用户提示,按需调整即可 Toast.makeText(Profile.this, "数据加载失败,请重试", Toast.LENGTH_SHORT).show(); } }); } public void update(View view){ if(isNamechanged()||isEmailchanged()){ Toast.makeText(this,"数据已更新",Toast.LENGTH_LONG).show(); } else { Toast.makeText(this,"数据未发生变更",Toast.LENGTH_LONG).show(); } } // 修正判断逻辑,避免空指针 private boolean isEmailchanged() { String newEmail = email.getText().toString().trim(); if (!mail.equals(newEmail)) { reference.child("Driver").child(userID).child("mail").setValue(newEmail); mail = newEmail; return true; } else { return false; } } private boolean isNamechanged() { String newName = Username.getText().toString().trim(); if (!name.equals(newName)) { reference.child("Driver").child(userID).child("username").setValue(newName); name = newName; return true; } else { return false; } } }
补充说明
你原有布局里的android:onClick="update"配置不需要修改,上述修改已经完全适配你的现有调用逻辑,无需额外调整。
内容的提问来源于stack exchange,提问作者Mohammad Yusuf
相关产品推荐
相关产品推荐

