Android 带ViewHolder的ListView,文本视图更改内容
我有一个带有自定义Android 带ViewHolder的ListView,文本视图更改内容,android,listview,android-listview,Android,Listview,Android Listview,我有一个带有自定义光标或适配器的列表视图。在那里我有这样一个: if (Main.distance_unit.equals(Main.miValue)) { //[...] some code here which converts units holder.mi.setText(mileageResult + " " + Main.distance_unit); } else if (Main.dista
光标或适配器的列表视图
。在那里我有这样一个:
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
片段时,一切都很好,但是当再次向下和向上滚动时,单位消失了。我认为这是由视图持有者造成的,对吗?我怎样才能解决这个问题
整个代码,可能有几行愚蠢的代码。欢迎您提出更好的方法来完成这些事情:
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;
}
请参见此处的示例模式:
@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)引发的。这就是你的观点的原因
状态属性未更新。您每次都在创建一个新的ViewHolder()
。如果convertView
为空,则需要创建一个新实例。如果convertView
不为空,则获取保持架。在任何一种情况下,都需要为视图设置值。你用错了图案。请查看下面解释如何正确使用视图支架的示例代码:
@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;
}
信用/来源:可能是bcoz listview回收视图请在完成后为我们调试“MyCusorAdapter”的整个代码的方法存在问题。谢谢@Raghunandan是的,我在问题中提到了这一点。我不知道怎么解决这个问题。谢谢。现在我开始了解ViewHolder
的工作原理。