我有ListView
个自定义CursorAdapter
。在那里我有这个:
if (Main.distance_unit.equals(Main.miValue)) {
//[...] some code here which converts units
holder.mi.setText(mileageResult + " " + Main.distance_unit);
} else if (Main.distance_unit.equals(Main.km)) {
holder.mi.append(" " + Main.distance_unit);
}
现在的问题是,当我第一次打开ListView
片段时,一切都很好,但是当再次向下滚动时,单位会消失。我认为这是由ViewHolder
引起的吗?我该如何解决这个问题?
整个代码,可能是一些愚蠢的代码行。欢迎您建议更好的方法来做这些事情:
public MyCursorAdapter(Context context, Cursor c, String[] from, int[] to) {
//noinspection deprecation
super(context, R.layout.activity_db_row, c, from, to);
mCursor = c;
ctx = context;
mInflater = LayoutInflater.from(ctx);
}
@Override
public View getView(int position, View v, ViewGroup parent) {
super.getView(position, v, parent);
mCursor.moveToPosition(position);
ViewHolder holder = new ViewHolder();
if (v == null) {
mInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = mInflater.inflate(R.layout.activity_db_row, parent, false);
//noinspection deprecation
v.setBackgroundDrawable(null);
DecimalFormatSymbols dfs = new DecimalFormatSymbols();
dfs.setDecimalSeparator('.');
decimalFormat.setDecimalFormatSymbols(dfs);
decimalFormatGal.setDecimalFormatSymbols(dfs);
holder.price = (RobotoTextView) v.findViewById(R.id.lv_tprice_unit);
holder.price.setText(Main.money_unit);
holder.lprice = (RobotoTextView) v.findViewById(R.id.lv_lprice_unit);
holder.lprice.setText(Main.money_unit + "/" + Main.amount_unit);
holder.amount_unit = (RobotoTextView) v.findViewById(R.id.lv_amount_unit);
if (Main.amount_unit.equals(Main.galValueImp)) {
holder.amount_unit.setText(Main.galValue);
} else holder.amount_unit.setText(Main.amount_unit);
bindView(v, ctx, mCursor);
holder.am = (RobotoTextView) v.findViewById(R.id.lv_amount);
String amount = holder.am.getText().toString();
holder.am.setText(String.valueOf(decimalFormatGal.format(Double.parseDouble(amount))));
holder.mi = (RobotoTextView) v.findViewById(R.id.lv_mileage);
String mileage = holder.mi.getText().toString();
holder.tp = (RobotoTextView) v.findViewById(R.id.lv_tprice);
String tprice = holder.tp.getText().toString();
holder.tp.setText(String.valueOf(decimalFormat.format(Double.parseDouble(tprice))));
holder.lp = (RobotoTextView) v.findViewById(R.id.lv_lprice);
holder.d = (RobotoTextView) v.findViewById(R.id.lv_date);
holder.fuel = (RobotoTextView) v.findViewById(R.id.lv_fueltype);
String fueltype = holder.fuel.getText().toString();
if(fueltype.equals("null") || fueltype.length() == 0) {
holder.fuel.setText("");
//ToDo: Remove at some point
}
String amountResult;
if (Main.amount_unit.equals(Main.galValue)) {
BigDecimal amountTmp, toGal, resultTmp;
double amountDouble = Double.parseDouble(amount);
amountTmp = BigDecimal.valueOf(amountDouble);
toGal = BigDecimal.valueOf(DbAdapter.toGal);
resultTmp = amountTmp.multiply(toGal).setScale(2,
RoundingMode.HALF_UP);
amountResult = resultTmp.toString();
holder.am.setText(String.valueOf(decimalFormat.format(Double.parseDouble(amountResult))));
}
if (Main.amount_unit.equals(Main.galValueImp)) {
BigDecimal amountTmp, toImpGal, resultTmp;
double amountDouble = Double.parseDouble(amount);
amountTmp = BigDecimal.valueOf(amountDouble);
toImpGal = BigDecimal.valueOf(DbAdapter.toImpGal);
resultTmp = amountTmp.multiply(toImpGal).setScale(2,
RoundingMode.HALF_UP);
amountResult = resultTmp.toString();
holder.am.setText(String.valueOf(decimalFormat.format(Double.parseDouble(amountResult))));
}
if (Main.distance_unit.equals(Main.miValue)) {
BigDecimal mileageTmp, toMi, resultTmp;
double mileageDouble = Double.parseDouble(mileage);
mileageTmp = BigDecimal.valueOf(mileageDouble);
toMi = BigDecimal.valueOf(DbAdapter.toMi);
resultTmp = mileageTmp.multiply(toMi).setScale(2,
RoundingMode.HALF_UP);
String mileageResult = resultTmp.toString();
holder.mi.setText(mileageResult + " " + Main.distance_unit);
} else if (Main.distance_unit.equals(Main.km)) {
holder.mi.append(" " + Main.distance_unit);
}
v.setTag(holder);
} else holder = (ViewHolder) v.getTag();
return v;
}
public static class ViewHolder {
RobotoTextView price;
RobotoTextView lprice;
RobotoTextView amount_unit;
RobotoTextView am;
RobotoTextView mi;
RobotoTextView tp;
RobotoTextView lp;
RobotoTextView d;
RobotoTextView fuel;
}
答案 0 :(得分:2)
请参阅此处的示例模式:
@Override
public View getView(int position, View v, ViewGroup parent) {
mCursor.moveToPosition(position);
if (v == null) {
/* inflate your view if "v" is null */
mInflater = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = mInflater.inflate(R.layout.activity_db_row, parent, false);
/* hold the reference of your view through ViewHolder */
ViewHolder holder = new ViewHolder();
holder.price = (RobotoTextView) v.findViewById(R.id.lv_tprice_unit);
......
/* set view tag */
v.setTag(holder);
}
/* This is where you should update your view state values */
ViewHolder holder = (ViewHolder) v.getTag();
DecimalFormatSymbols dfs = new DecimalFormatSymbols();
dfs.setDecimalSeparator('.');
decimalFormat.setDecimalFormatSymbols(dfs);
holder.price.setText(Main.money_unit);
..... update view's
return v;
}
您的示例代码段会发生什么?在listview的第一次迭代。您的代码片段工作正常 因为视图基本上还没有被回收。在你的问题上。这是视图得到回收。 由于视图可能已经被回收,因此不会执行if(v == null)。这就是为什么你的观点 状态属性未更新。
答案 1 :(得分:0)
您每次都在创建new ViewHolder()
。如果convertView
为null,则需要创建新实例。如果convertView
不为null,则获取持有者。在任何一种情况下,您都需要将值设置为视图。你使用的模式错了。请查看下面的示例代码,其中说明了如何正确使用视图持有者:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderItem viewHolder;
/*
* The convertView argument is essentially a "ScrapView" as described is Lucas post
* http://lucasr.org/2012/04/05/performance-tips-for-androids-listview/
* It will have a non-null value when ListView is asking you recycle the row layout.
* So, when convertView is not null, you should simply update its contents instead of inflating a new row layout.
*/
if(convertView==null){
// inflate the layout
LayoutInflater inflater = ((Activity) mContext).getLayoutInflater();
convertView = inflater.inflate(layoutResourceId, parent, false);
// well set up the ViewHolder
viewHolder = new ViewHolderItem();
viewHolder.textViewItem = (TextView) convertView.findViewById(R.id.textViewItem);
// store the holder with the view.
convertView.setTag(viewHolder);
}else{
// we've just avoided calling findViewById() on resource everytime
// just use the viewHolder
viewHolder = (ViewHolderItem) convertView.getTag();
}
// object item based on the position
ObjectItem objectItem = data[position];
// assign values if the object is not null
if(objectItem != null) {
// get the TextView from the ViewHolder and then set the text (item name) and tag (item ID) values
viewHolder.textViewItem.setText(objectItem.itemName);
viewHolder.textViewItem.setTag(objectItem.itemId);
}
return convertView;
}
致谢/来源:http://www.javacodegeeks.com/2013/09/android-viewholder-pattern-example.html