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

ListView中EditText绑定addTextChangedListener运行异常问题求助

重量单位转换功能修复方案

问题根因

  • TextWatcher多次触发:每次getView执行时都会给EditText绑定新的TextWatcher,ListView复用item时会导致一个EditText绑定多个监听器,单次输入触发多次回调;同时调用setText更新数值时会再次触发TextWatcher,形成循环触发。
  • 数值计算错误:换算逻辑没有统一基准值,错误使用动态变化的unitWeightValueUpdated参与计算,同时匿名内部类直接引用外部的position和viewHolder,item复用时会指向错误的位置,导致取值计算错误。

修复后完整代码

仅需要替换convAdapter.java即可,其余代码无需调整:

public class convAdapter extends BaseAdapter {
    DecimalFormat format = new DecimalFormat("0.########");
    private String unitWeight[] = {"Pound","Kilogram","Gram"};
    // 存储1千克对应的各单位数值,作为固定换算基准
    private String unitWeightRate[] = {"2.204","1","1000"};
    // 存储当前各单位的实际展示数值
    private String unitWeightValue[] = {"2.204","1","1000"};
    private Activity activity;
    private LayoutInflater inflater=null;
    // 控制计算刷新时不触发TextWatcher回调,避免循环
    private boolean isCalculating = false;

    public convAdapter(Activity a) {
        activity = a;
        inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    public int getCount() {
        return unitWeight.length;
    }

    public Object getItem(int position) {
        return position;
    }

    public long getItemId(int position) {
        return position;
    }


    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        if(convertView==null){
            convertView = inflater.inflate(R.layout.unit_row, null);
            viewHolder = new ViewHolder(convertView);
            convertView.setTag(viewHolder);
        }else{
            viewHolder = (ViewHolder) convertView.getTag();
            // 复用item时先移除旧的监听器,避免重复绑定
            if(viewHolder.watcher != null){
                viewHolder.etValue.removeTextChangedListener(viewHolder.watcher);
            }
        }

        viewHolder.currentPosition = position;
        viewHolder.txtItem.setText(unitWeight[position]);
        viewHolder.etValue.setText(format.format(Double.parseDouble(unitWeightValue[position])));

        // 新建监听器绑定到当前item
        TextWatcher watcher = new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {}
            @Override
            public void afterTextChanged(Editable s) {
                String input = s.toString().trim();
                // 刷新状态下或者输入为空直接跳过
                if(input.isEmpty() || isCalculating){
                    return;
                }
                double inputVal;
                try {
                    inputVal = Double.parseDouble(input);
                } catch (NumberFormatException e) {
                    return;
                }
                // 先把输入值转换为千克基准值
                double kgBase = inputVal / Double.parseDouble(unitWeightRate[viewHolder.currentPosition]);
                // 批量计算所有单位的数值
                for(int i=0; i<unitWeight.length; i++){
                    double res = kgBase * Double.parseDouble(unitWeightRate[i]);
                    unitWeightValue[i] = format.format(res);
                }
                // 刷新列表,设置标志位避免触发回调
                isCalculating = true;
                notifyDataSetChanged();
                isCalculating = false;
            }
        };
        viewHolder.watcher = watcher;
        viewHolder.etValue.addTextChangedListener(watcher);
        return convertView;
    }

    private class ViewHolder {
        TextView txtItem;
        EditText etValue;
        TextWatcher watcher;
        int currentPosition;

        public ViewHolder(View view) {
            txtItem = view.findViewById(R.id.tvUnitName);
            etValue = view.findViewById(R.id.etValue);
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 12:57:03