我有一个带有自定义 ArrayAdapter 的 ListView,它使用OrderedProductItems
(我自己的模型类)列表。在这个 ArrayAdapter 的 getView 中,我使用了 ViewHolder 设计模式:
@Override
public View getView(int position, View convertView, ViewGroup parent){
View view = convertView;
MyHolder h;
if(view == null){
view = inflater.inflate(layoutResourceId, parent, false);
RelativeLayout rl = (RelativeLayout) view.findViewById(R.id.item_layout);
h = new MyHolder(rl);
view.setTag(h);
}
else
h = (MyHolder) view.getTag();
if(h != null){
h.orderedProductItem = getItem(position);
... // Do stuff like:
// - setting Texts of TextViews/EditText
// - updating data of AutoCompleteTextView and Spinner
// - etc.
h.etResultPrice.setTag(h.orderedProductItem);
h.etResultPrice.addTextChangedListener(new MyTextWatcher(h.etResultPrice));
}
}
在我的 ListView 的项目中,我有一个使用自定义 TextWatcher 的 EditText。在这个 TextWatcher 中,我将用户的输入保存到我的 OrderedProductItem 类:
public class MyTextWatcher implements TextWatcher
{
// Logcat tag
private static final String TAG = "MyTextWatcher";
// The values used for the test output of changed EditText texts
private View view;
private String from;
public MyTextWatcher(View v){
view = v;
}
// Default Android method used by TextWatcher
// (to do something before an EditText's is going to change)
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
// Get the old text before we make a change to this EditText
from = ((EditText)view).getText().toString();
}
// Default Android method used by TextWatcher
// (to do something when an EditText's text is changing)
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
// Default Android method used by TextWatcher
// (to do something after an EditText's text is changed)
@Override
public void afterTextChanged(Editable s) {
if(s != null && s.toString() != null && view.getTag() != null){
OrderedProductItem opi = (OrderedProductItem)view.getTag();
if(opi != null){
// Send the changed text of this EditText to the OrderedProductItem's Result-values
if(view.getId() == R.id.et_result_amount){
int amount = 1;
try{
amount = Integer.parseInt(s.toString());
}
catch(NumberFormatException ex){
amount = 1;
}
if(opi.getResultAmount() != amount){
opi.setResultAmount(amount);
Log.i(TAG, "ResultAmount changed from " + from + " to " + s.toString() + " (-> " + String.valueOf(opi.getResultAmount()) + ")");
}
}
else if(view.getId() == R.id.actv_result_name){
if(!V.compare(opi.getResultName(), s.toString(), false, false)){
opi.setResultName(s.toString());
Log.i(TAG, "ResultName changed from " + from + " to " + s.toString() + " (-> " + opi.getResultName() + ")");
}
}
else if(view.getId() == R.id.et_result_price){
double price = C.priceStringToDouble(s.toString());
if(opi.getResultPrice() != price){
opi.setResultPrice(price);
Log.i(TAG, "ResultPrice changed from " + from + " to " + s.toString() + " (-> " + String.valueOf(opi.getResultPrice()) + ")");
}
}
}
else
Log.wtf(TAG, "Tag's OrderedProductItem is null");
}
}
}
现在我的问题是这样的:由于 ArrayAdapter 使用 getView-recycler(有关 getView 回收(包括图片)的更多信息,请参阅这篇文章),我的 TextWatcher 会覆盖另一个 OrderedProductItem 的不正确数据。例如,假设我的 OrderedProductItem 的 EditTexts 在创建时像这样填充(这里没有错):
- 预期的“1”——实际的“1”
- 预期的“2”——实际的“2”
- 预期的“3”——实际的“3”
- 预期的“4”——实际的“4”
- 预期的“5”——实际的“5”
- 预期的“6”——实际的“6”
- 预期的“7”——实际的“7”
- 预期的“8”——实际的“8”
- 预期的“9”——实际的“9”
- 预期“10”——实际“10”
现在当我向下滚动时,会发生以下情况(仍然没有错):
- 预期的“5”——实际的“5”
- 预期的“6”——实际的“6”
- 预期的“7”——实际的“7”
- 预期的“8”——实际的“8”
- 预期的“9”——实际的“9”
- 预期“10”——实际“10”
- 预期的“11”——实际的“11”
- 预期的“12”——实际的“12”
- 预期的“13”——实际的“13”
- 预期的“14”——实际的“14”
当我向上滚动时,问题出现了:
- 预期的“1”——实际的“14”
- 预期的“2”——实际的“13”
- 预期“3”——实际“12”
- 预期“4”——实际“11”
- 预期的“5”——实际的“5”
- 预期的“6”——实际的“6”
- 预期的“7”——实际的“7”
- 预期的“8”——实际的“8”
- 预期的“9”——实际的“9”
- 预期“10”——实际“10”
我确实尝试在 getView 开始时暂时禁用 TextWatcher(在我获得 EditTexts 之后),然后从 OrderedProductItem 设置值,然后将 MyTextWatcher 重新应用到它们,但是在我重新之后它仍然会更改 OrderedProductItem 的值-应用了我的 TextWatcher ..
有谁知道在使用 TextWatcher 保存 Item 的 EditTexts 的 UserInput 时如何处理 getView 回收?
PS:我知道我可以在 EditTexts 旁边添加一个按钮,所以它只在单击按钮时保存数据,但我不想要这个。