登录界面ProgressDialog卡顿,无法启动新Activity问题求助
解决SignIn界面ProgressDialog卡顿及无法启动Activity的问题
看了你的代码和调试日志,我来帮你梳理问题根源和对应的修复方案:
1. 核心卡顿原因:Firebase监听使用不当
你在登录逻辑里用了addValueEventListener,这个方法会持续监听数据节点的所有变化,但登录只需要单次查询用户信息就够了。这种永久监听会导致:
- 不必要的重复回调,占用UI线程资源引发卡顿
- 登录成功后监听依然存在,浪费设备资源
修复方案:把addValueEventListener替换为addListenerForSingleValueEvent,它只会执行一次数据查询,完成后自动取消监听:
users.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { // 保留你原有的用户校验逻辑 } @Override public void onCancelled(DatabaseError databaseError) { // 这里必须关闭Dialog,避免请求失败后弹窗一直挂着 mDialog.dismiss(); Toast.makeText(SignIn.this,"登录请求失败:"+databaseError.getMessage(),Toast.LENGTH_SHORT).show(); } });
2. ProgressDialog生命周期管理漏洞
你的代码只在onDataChange里关闭Dialog,但如果网络中断、请求被取消,Dialog会一直停留在界面,造成"卡顿"的假象。
修复方案:
- 必须在
onCancelled方法中也调用mDialog.dismiss() - 可以在Activity销毁时做兜底处理,避免内存泄漏:
@Override protected void onDestroy() { super.onDestroy(); if(mDialog != null && mDialog.isShowing()){ mDialog.dismiss(); } }
3. 日志中RippleDrawable报错(非卡顿主因)
日志里的Could not find class 'android.graphics.drawable.RippleDrawable'是AppCompat库的兼容警告——你的设备API版本低于21(RippleDrawable在API21才引入)。这个警告不影响功能,若要消除可以:
- 升级
app/build.gradle里的AppCompat库到最新稳定版 - 把布局中类似
android:background="?attr/selectableItemBackground"的属性,替换为AppCompat兼容的app:background="?attr/selectableItemBackground"
4. 代码结构优化(提升可读性与稳定性)
你把signInUser方法嵌套在onClick监听内部,虽然语法合法,但可读性差还可能引发上下文引用问题。建议提取为Activity的成员方法:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_sign_in); // 初始化控件... btnSignIn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { signInUser(edtPhone.getText().toString(),edtPassword.getText().toString()); } }); } // 提取为独立的成员方法 private void signInUser(String phone, String password) { final ProgressDialog mDialog=new ProgressDialog(SignIn.this); mDialog.setMessage("Please wait..."); mDialog.show(); final String localPhone=phone; final String localPassword=password; users.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { mDialog.dismiss(); if (dataSnapshot.child(localPhone).exists()) { User user=dataSnapshot.child(localPhone).getValue(User.class); user.setPhone(localPhone); if (Boolean.parseBoolean(user.getIsStaff())) { if (user.getPassword().equals(localPassword)) { Intent login =new Intent(SignIn.this,Home.class); Common.currentUser=user; startActivity(login); finish(); } else { Toast.makeText(SignIn.this,"Wrong password",Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(SignIn.this,"Login with staff account",Toast.LENGTH_SHORT).show(); } } else { Toast.makeText(SignIn.this,"User not exist in database..",Toast.LENGTH_SHORT).show(); } } @Override public void onCancelled(DatabaseError databaseError) { mDialog.dismiss(); Toast.makeText(SignIn.this,"Login failed: "+databaseError.getMessage(),Toast.LENGTH_SHORT).show(); } }); }
额外小建议
- 登录前先做输入校验(比如手机号、密码是否为空),避免无效的网络请求
- 考虑用
AlertDialog或Material Design的DialogFragment替代已被废弃的ProgressDialog(Android O开始标记为废弃)
内容的提问来源于stack exchange,提问作者Bhaskar Joshi
相关产品推荐
相关产品推荐

