You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中无需点击按钮自动计算填充BMI EditText失败求助

解决自动计算BMI及数据库存储问题

Hey there! Let's work through why your BMI isn't calculating automatically and fix the database issue too. Here are the key problems and their fixes:

1. 你忘记给身高/体重输入框绑定TextWatcher了

你已经实现了TextWatcher接口,但没有告诉etHeight和etWeight这两个输入框要监听文本变化,所以输入内容时不会触发calculate()方法。

在onCreate()方法里初始化完所有EditText后,加上这两行代码:

etHeight.addTextChangedListener(this);
etWeight.addTextChangedListener(this);

2. BMI计算逻辑有两个关键错误

你当前的公式用了整数除法(会直接截断小数),而且没有把身高从厘米转换成米——这会导致计算结果极小甚至为0。我们重写calculate()方法,同时加入输入校验:

private void calculate() {
    String heightInput = etHeight.getText().toString().trim();
    String weightInput = etWeight.getText().toString().trim();

    // 如果输入为空,清空BMI显示
    if (heightInput.isEmpty() || weightInput.isEmpty()) {
        etBMI.setText("");
        return;
    }

    try {
        // 将身高从厘米转为米,用double类型保证计算精度
        double heightInMeters = Double.parseDouble(heightInput) / 100.0;
        double weightInKg = Double.parseDouble(weightInput);

        // 校验身高为有效正数
        if (heightInMeters <= 0) {
            etBMI.setText("无效身高");
            return;
        }

        // 计算BMI并保留两位小数,让结果更友好
        double bmiValue = weightInKg / (heightInMeters * heightInMeters);
        etBMI.setText(String.format("%.2f", bmiValue));
    } catch (NumberFormatException e) {
        // 处理非数字输入的情况
        etBMI.setText("输入无效");
    }
}

3. 数据库插入存在校验和安全漏洞

你当前的代码没有在插入数据库前校验输入是否为空或有效,容易导致崩溃或存入空值;而且用字符串拼接SQL语句有SQL注入风险。我们修复btnNext的点击事件:

首先,修正全局btnNext变量的定义(你之前在局部重新定义了变量,虽然不影响但不够规范):

// 把这行:
// Button btnNext = (Button) findViewById(R.id.btnNext);
// 改成:
btnNext = (Button) findViewById(R.id.btnNext);

然后更新点击事件逻辑:

btnNext.setOnClickListener(new OnClickListener() {
    public void onClick(View V) {
        String name = etName.getText().toString().trim();
        String ageStr = etAge.getText().toString().trim();
        String heightStr = etHeight.getText().toString().trim();
        String weightStr = etWeight.getText().toString().trim();
        String bmi = etBMI.getText().toString().trim();

        // 检查所有必填字段是否填写
        if (name.isEmpty() || ageStr.isEmpty() || heightStr.isEmpty() || weightStr.isEmpty() || bmi.isEmpty()) {
            Toast.makeText(Userreg.this, "请填写所有必填字段", Toast.LENGTH_SHORT).show();
            return;
        }

        try {
            int age = Integer.parseInt(ageStr);
            int height = Integer.parseInt(heightStr);
            int weight = Integer.parseInt(weightStr);

            // 使用参数化SQL防止SQL注入风险
            String sql = "INSERT INTO UserInfo (Name,Age,Height,Weight,BMI) VALUES (?, ?, ?, ?, ?)";
            db.execSQL(sql, new Object[]{name, age, height, weight, bmi});

            Toast.makeText(Userreg.this, "注册成功!", Toast.LENGTH_SHORT).show();
            Intent msg3 = new Intent(Userreg.this, Regsuccess.class);
            startActivity(msg3);
        } catch (NumberFormatException e) {
            Toast.makeText(Userreg.this, "年龄、身高、体重请输入有效数字", Toast.LENGTH_SHORT).show();
        } catch (Exception e) {
            Toast.makeText(Userreg.this, "数据库错误:" + e.getMessage(), Toast.LENGTH_LONG).show();
        }
    }
});

4. 额外优化:数据库存储位置与资源清理

你当前把数据库存在SD卡根目录,需要额外权限且不安全。改用内部存储更稳妥,不需要额外权限:

String createDatabase(String sql, String dbName) {
    try {
        // 使用内部存储(无需权限)
        db = openOrCreateDatabase(dbName, MODE_PRIVATE, null);
        db.execSQL(sql);
    } catch (Exception e) {
        Toast.makeText(this, e.getMessage(), Toast.LENGTH_LONG).show();
        return "Error opening DB";
    }
    return "";
}

同时,在onDestroy()里关闭数据库,避免资源泄漏:

@Override
protected void onDestroy() {
    super.onDestroy();
    if (db != null && db.isOpen()) {
        db.close();
    }
}

把这些修改全部应用后,用户输入身高体重时BMI会自动计算填充,数据库也能正确存储有效数据了。

内容的提问来源于stack exchange,提问作者Kelvin How

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:57:38