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
相关产品推荐
相关产品推荐

