Android Studio中如何根据Spinner选中值跳转对应角色Activity
问题根因分析
- 校验逻辑缺失:当前SQL查询仅匹配邮箱和密码,未加入
用户角色匹配条件,只要账号密码正确,不管对应账号在库里的角色是不是你选的,都会往下走 - 执行顺序完全颠倒:
rs.next()返回true才代表查到了匹配的用户,你现在是查到用户就直接return,反而在查不到用户的时候执行跳转逻辑,这就是为什么不管校验成不成功都乱跳 - 线程使用错误:
doInBackground运行在工作线程,不能直接执行startActivity这类UI操作,所有页面跳转、Toast操作必须放到UI线程的onPostExecute里执行 - Spinner取值对比错误:
user_type.getSelectedItem()返回的是Object类型,直接和字符串对比永远返回false,必须先调用toString()转成字符串再对比
修正步骤
- 调整SQL查询逻辑,加入角色字段过滤(假设你库里用户表的角色字段名叫
user_role,如果你的字段名不一样自行替换) - 把跳转逻辑移到
onPostExecute中,校验通过再执行跳转 - 修复Spinner取值和逻辑顺序问题
- 用
PreparedStatement替代Statement避免SQL注入风险
修正后完整代码
private class login_Api extends AsyncTask<String,String,String> { // 存储当前选中的角色,方便后续跳转使用 private String selectedRole; @Override protected void onPreExecute() { Toast.makeText(LoginActivity.this, "logging-in ... ", Toast.LENGTH_SHORT).show(); // 提前在UI线程拿到选中的角色,不要在工作线程操作UI控件 selectedRole = user_type.getSelectedItem().toString().trim(); } @Override protected String doInBackground(String... strings) { try { Connection con = connectionClass.CONN(); if (con != null) { // 查询条件加入角色匹配,避免越权登录 String query = "SELECT * FROM `users` WHERE email = ? and password = ? and user_role = ?"; PreparedStatement pstmt = con.prepareStatement(query); pstmt.setString(1, texEmail.getText().toString().trim()); pstmt.setString(2, texPassword.getText().toString().trim()); pstmt.setString(3, selectedRole); ResultSet rs = pstmt.executeQuery(); // 查到匹配的用户才返回成功标识 if (rs.next()) { // 返回用户id或者自定义的成功标识,不为空代表校验通过 return rs.getString(1); } // 没查到匹配的返回空,代表账号/密码/角色不匹配 return null; } else { Log.d(TAG, "onPreExecute: 数据库连接失败"); return "conn_error"; } } catch (Exception e) { Log.d(TAG, "onPreExecute: 查询出错" + e.getMessage()); return "error"; } } @Override protected void onPostExecute(String result) { Log.d(TAG, "onPostExecute: "+result); if(result != null && !result.equals("error") && !result.equals("conn_error")) { Toast.makeText(LoginActivity.this, "Welcome... ", Toast.LENGTH_SHORT).show(); // 校验通过后根据选中的角色跳转对应页面 if (selectedRole.equals("Hospital")) { Intent intent1 = new Intent(LoginActivity.this, HospitalMain.class); startActivity(intent1); finish(); // 可选,关闭登录页避免按返回键回到登录页 } else if (selectedRole.equals("Donor")) { Intent intent1 = new Intent(LoginActivity.this, AddHospitalActivity.class); startActivity(intent1); finish(); } // 剩余第三类角色的跳转逻辑在此处补充即可 } else { if(result.equals("conn_error")){ Toast.makeText(LoginActivity.this, "数据库连接失败", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(LoginActivity.this, "账号/密码或角色不匹配", Toast.LENGTH_SHORT).show(); } } } }
补充注意事项
- 如果你的用户表角色字段名不是
user_role,记得把SQL语句里的字段名替换成你实际使用的字段名 - 不要明文存储密码到数据库,生产环境建议加密后存储,查询时也先把输入的密码加密再和库中数据匹配
- AsyncTask已被官方废弃,后续迭代建议用
Coroutines、RxJava或者WorkManager替代异步逻辑
内容的提问来源于stack exchange,提问作者user17327197
相关产品推荐
相关产品推荐

