目标:应用程序应允许用户为显示的项目添加数量。考虑从所有可能产品的列表中创建产品订单。产品代码列表可能很长(如数万件甚至更多)。另一方面,订单所选项目的数量非常小(最多几个或几十个)。
已实施:到目前为止,我已实施了使用OrderOverviewActivity
的{{1}}和内容提供商,以便从数据库中访问信息。我使用扩展LoaderManager
的{{1}}并覆盖其MyCursorAdapter
和CursorAdapter
方法。
newView()
还会创建一个bindView()
实例,其中包含对子视图的引用,以及从光标位置提取的值的缓冲区 - 如下所示:
newView()
ViewHolder
看起来像这样:
private static class ViewHolder {
public TextView code;
public CharArrayBuffer codeBuffer = new CharArrayBuffer(20);
public TextView name;
public CharArrayBuffer nameBuffer = new CharArrayBuffer(100);
public TextView quantity;
public CharArrayBuffer quantityBuffer = new CharArrayBuffer(10);
}
newView()
使用holder缓冲区来避免创建许多 public View newView(Context context, Cursor cursor, ViewGroup parent) {
View v = mInflater.inflate(mLayout, parent, false);
ViewHolder holder = new ViewHolder();
holder.code = (TextView) v.findViewById(R.id.code);
holder.name = (TextView) v.findViewById(R.id.name);
holder.quantity = (TextView) v.findViewById(R.id.quantity);
v.setTag(holder);
return v;
}
个对象:
bindView()
问题的核心:请注意,数量是通过String
从 public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
cursor.copyStringToBuffer(1, holder.codeBuffer); // ProductTable.COLUMN_CODE
cursor.copyStringToBuffer(2, holder.nameBuffer); // ProductTable.COLUMN_NAME
holder.code.setText(holder.codeBuffer.data, 0, holder.codeBuffer.sizeCopied);
holder.name.setText(holder.nameBuffer.data, 0, holder.nameBuffer.sizeCopied);
// The quantity (v for value) from the HashMap<String, String>.
String v = mQuantity.get(String.valueOf(holder.codeBuffer.data, 0,
holder.codeBuffer.sizeCopied));
if (v != null) {
holder.quantity.setText(v);
holder.quantity.setBackgroundColor(Color.DKGRAY);
}
else {
holder.quantity.setText(null);
holder.quantity.setBackgroundColor(Color.TRANSPARENT);
}
}
对象中提取的。我担心它会创建一个字符串对象,以后必须进行垃圾回收,从而破坏性能。有没有更好的方法从地图设置数量TextView值?
答案 0 :(得分:1)
我不同意yanchenko对CharArrayBuffer
的看法,在基于Cursor
的适配器中使用它是一个很好的改进(特别是当Cursor
有许多String
列时使用)。要摆脱额外的String
,第一个选项就是将其作为mQuantity
HashMap
无效的关键(而且它是final
的类,这样你就可以它根本不起作用。
标识行的另一种方法是_id
所需的ListView
列。
与此相关,您可以:
让两个HashMap
都具有Long
值作为关键字(_id),其中一个将保留COLUMN_CODE
,另一个将保留实际数量(或_id
和代码之间的一个地图映射,另一个是您当前的地图。这两个映射将被同步(如果你为一个长id删除一个值,你也将它从另一个中删除,当你添加值时也是如此)。在getView()
方法中,您可以使用Cursor
中的_id获取名称,但这需要自动装箱操作(long
到Long
)。
class DataWrapper {
private HashMap<Long, String> mCodeMapping = new HashMap<Long, String>();
private HashMap<Long, String> mQuantityMapping = new HashMap<String, String>();
public String getCode(long id) {
return mCodeMapping.get(id);
}
public String getQuantity(long id) {
return mQuantityMapping.get(getCode());
}
public String getQuantity(String code) {
return mQuantityMapping.get(code);
}
public void put(long id, String code, String quantity) {
mCodeMapping.put(id, code);
mQuantityMapping .put(code, quantity);
}
}
虽然_id
是long
并且您拥有相当数量的值,但您可以将其威胁为int
(因为您将在int
的边界内最大SparseArray
个值)。这样做可以让您只使用long
自定义类(在int
和class WrapperData {
String code; //or use the CharArraybuffer?
String quantity;
}
SparseArray<WrapperData> data = new SparseArray<WrapperData>();
// in the getView() method
WrapperData wd = data.get((int) _id_value); // further use wd.code or wd.quantity
之间进行投射):
SparseArray
最后一个选项是实现自己的类,如long
,它允许您在简单的{{1}}键(因此没有自动装箱)与代码和数量值之间进行映射。
答案 1 :(得分:0)
将字符串变量添加到ViewHolder类中,作为为Holder类分配并与位置映射的克隆内存实例。除了刚刚完成赋值使用NEW关键字,所以你将获得未与HASHMAP映射的新STRING对象。
私有静态类ViewHolder {
public String quantityStr;
public TextView code;
public CharArrayBuffer codeBuffer = new CharArrayBuffer(20);
public TextView name;
public CharArrayBuffer nameBuffer = new CharArrayBuffer(100);
public TextView quantity;
public CharArrayBuffer quantityBuffer = new CharArrayBuffer(10);
}
public查看newView
{ ... holder.quantityStr = new String (mQuantity.get(String.valueOf(holder.codeBuffer.data,0,holder.codeBuffer.sizeCopied)));
}
答案 2 :(得分:0)
我认为它不会创建一个新的字符串实例,因为字符串常量池中已经存在一个字符串常量。
String str = "test";
String str2 = "test";
char[] strArray = {'t', 'e', 's','t'};
System.out.println(str.hashCode());
System.out.println(str2.hashCode());
System.out.println(String.valueOf(strArray).hashCode());
结果与打击相同: 3556498 3556498 3556498
答案 3 :(得分:0)
我宁愿不与CharArrayBuffer
混在一起,也不会在String
中使用TextView
s + Holder
。
这样您就可以使代码更具可读性,并让平台使用String池进行缓存。这也意味着最佳表现。
即
private static class ViewHolder {
public TextView code;
public TextView name;
public TextView quantity;
}
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
String code = cursor.getString(1);
String name = cursor.getString(2);
String quantity = mQuantity.get(code);
holder.code.setText(code);
holder.name.setText(name);
if (quantity != null) {
holder.quantity.setText(quantity);
holder.quantity.setBackgroundColor(Color.DKGRAY);
} else {
holder.quantity.setText("");
holder.quantity.setBackgroundColor(Color.TRANSPARENT);
}
}
我建议你先运行一系列3个性能分析测试:
String v =
mQuantity.get(String.valueOf(holder.codeBuffer.data, 0,
holder.codeBuffer.sizeCopied));
来电。根据结果选择最后两个之间最易读的结果。 (: