我必须创建一个自定义组件(我不能使用gridview或dataTable),这是一个包含6列和X行(没有图像)的表。下图显示了它的工作原理:
当我在该表上向上或向下滚动时,会出现问题。有时它会正确滚动,而在其他情况下则需要延迟。在logcat中,我意识到GC启动时会出现延迟。
我一直在寻找一种优化组件的方法,但我不熟悉Java。我读到了关于优化视图和重用对象宽度getView的内容。下面是我当前的getView代码:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (null == this.parent)
this.parent = (ListViewOT) parent;
if (this.parent.isInEditMode()) {
super.getView(position, convertView, parent);
}
mActivity = (MainActivity) parent.getContext();
this.c = this.getCursor();
c.moveToPosition(position);
if (null == convertView) {
view = (LinearLayout) LinearLayout.inflate(
this.context, R.layout.item_lvacoes, null);
row = (LinearLayout) view.getChildAt(1);
headerRow = (TableRow) this.parent.getHeader().getChildAt(0);
for (int j = 0; j < this.c.getColumnCount(); j++) {
columnName = c.getColumnName(j);
if (columnName.startsWith("Status")) {
continue;
}
headerCell = (CelulasLV) headerRow.getChildAt(j);
current_width = headerCell.getWidth();
headerCell.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
cell_width = AdapterLVAcoes.CalculateTextSize(headerCell.getPaint(), c.getColumnName(j));
column_width = this.parent.getColumnWidthAt(j);
if (column_width == 0)
headerCell.setWidth(0);
else if (cell_width <= column_width)
{
if (current_width != column_width)
headerCell.setWidth(column_width);
} else
{
this.changedWidth = true;
this.parent.setColumnWidthAt(j, cell_width);
}
column = new CelulasLV(this.context,(ListViewOT) parent);
if (columnName.equals("No"))
column.setText("" + (position + 1));
else
column.setText(c.getString(j));
column.setIndexColumn(j);
column.setIndexRow(position);
column.setEPC(c.getString(c.getColumnIndex("_id")));
int status = c.getInt(c.getColumnIndex("Status"));
if (status == 0)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cell));
else if (status == 1)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cellachado));
else if (status == 2)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cellextraviado));
else if (status == 3)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cellinexistente));
else if (status == 4)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cellpreachado));
activity.registerForContextMenu(column);
cell_width = AdapterLVAcoes.CalculateTextSize(column.getPaint(), column.getText().toString());
column_width = this.parent.getColumnWidthAt(j);
if (column_width == 0)
column.setWidth(0);
else if (cell_width <= column_width)
column.setWidth(column_width);
else
{
this.changedWidth = true;
this.parent.setColumnWidthAt(j, cell_width);
}
row.addView(column);
}
return view;
}
else
{
view = (LinearLayout) convertView;
row = (LinearLayout) view.getChildAt(1);
int i = 0;
headerRow = (TableRow) this.parent.getHeader().getChildAt(0);
{
for (int j = 0; j < this.c.getColumnCount(); j++)
{
columnName = c.getColumnName(j);
if (columnName.startsWith("Status")) {
continue;
}
headerCell = (CelulasLV) headerRow.getChildAt(j);
current_width = headerCell.getWidth();
headerCell.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
cell_width = AdapterLVAcoes.CalculateTextSize(headerCell.getPaint(), c.getColumnName(j));
column_width = this.parent.getColumnWidthAt(j);
if (column_width == 0)
headerCell.setWidth(0);
else if (cell_width <= column_width)
if (current_width != column_width)
headerCell.setWidth(column_width);
else
{
this.changedWidth = true;
this.parent.setColumnWidthAt(j, cell_width);
}
column = (CelulasLV) row.getChildAt(i);
if (columnName.equals("No"))
column.setText("" + (position + 1));
else
column.setText(c.getString(j));
column.setIndexColumn(j);
column.setIndexRow(position);
column.setRealIndex(c.getLong(c.getColumnIndex("No")));
column.setEPC(c.getString(c.getColumnIndex("_id")));
status = c.getInt(c.getColumnIndex("Status"));
if (status == 0)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cell));
else if (status == 1)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cellachado));
else if (status == 2)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cellextraviado));
else if (status == 3)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cellinexistente));
else if (status == 4)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cellpreachado));
activity.registerForContextMenu(column);
column.setOnClickListener(this.cellClick);
cell_width = AdapterLVAcoes.CalculateTextSize(column.getPaint(), column.getText().toString());
column_width = this.parent.getColumnWidthAt(j);
if (column_width == 0)
column.setWidth(0);
else if (cell_width <= column_width)
column.setWidth(column_width);
else
{
this.changedWidth = true;
this.parent.setColumnWidthAt(j, cell_width);
}
i++;
}
}
return convertView;
}
}
它基本上根据找到的最宽列重新绘制列。
如何优化我的组件,因此当GC投入使用时不会出现这些滞后?
提前致谢并抱歉英语不好。
答案 0 :(得分:1)
老兄,我只是看着这个和你的另一篇文章。让我们尝试使用你拥有的东西。在确定宽度时你有一些非常复杂的算法,但在我们解决这个问题之前,我们肯定能加快速度。我将对您应该做的事情进行更深入的概述。您必须将其转换为代码,因为这是一个复杂的问题。
您需要创建一个给定位置的缓存,而#列将存储测量的宽度。始终先检查您的缓存,然后仅测量是否找不到任何内容。每个位置可以调用getView()
方法3-4次。所以这应该会产生巨大的改善。
另一种方法是,如果您有大量动态文本或重复文本......您可以创建基于文本的缓存。因此,对于给定的String,您可以缓存测量的宽度。
假设您只是在列中显示文字,那么可以选择更快的替代测量解决方案。只需使用TextView的getPaint().measureText(String)
方法即可。它将返回文本的宽度(以像素为单位)。你可能需要增加一些4-8 dp的绒毛,但这可能比你正在做的更快。
缓存示例:
在适配器的构造函数中,执行以下操作:
Map<String, Float> mWidthCache = new HashMap<String, Float>();
然后在getView()
内的for循环中执行以下操作:
String key = String.valueOf(position) + c.getColumnName(j);
Float measuredWidth = mWidthCache.get(key);
if (width == null) {
//Calculate measuredWidth
mWidthCache.put(key, measuredWidth); //Then place back in cache
}
//Adjust width of layout based on measureWidth
答案 1 :(得分:0)
我相信GC会因为你在过多的记忆中流动而踢很多。
每次调用getView (...)
时都需要缓存它们而不是重新创建位图 - 只需创建一次并将它们存储在内存中,然后重复使用它们而不是重新加载它们。
创建新功能:
private Drawable getMyBackgroundDrawable (int status)
{
if (status == 0)
return a;
else if (status == 1)
return b;
else if (status == 2)
return c;
else if (status == 3)
return d;
else if (status == 4)
return e;
return null;
}
您需要在类体中定义缓存的drawable:
Drawable a;
Drawable b;
Drawable c;
Drawable d;
Drawable e;
在这个类的某处加载drawables(在构造函数中或在onFinishInflate
中通常是我的选择):
a = context.getResources().getDrawable(R.drawable.cell);
b = context.getResources().getDrawable(R.drawable.cellachado);
c = context.getResources().getDrawable(R.drawable.cellextraviado);
d = context.getResources().getDrawable(R.drawable.cellinexistente);
e = context.getResources().getDrawable(R.drawable.cellpreachado);
删除这些(你有两次):
if (status == 0)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cell));
else if (status == 1)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cellachado));
else if (status == 2)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cellextraviado));
else if (status == 3)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cellinexistente));
else if (status == 4)
column.setBackgroundDrawable(context.getResources().getDrawable(R.drawable.cellpreachado));
将其替换为:
column.setBackgroundDrawable(getMyBackgroundDrawable (status));
请注意,我还没有编译或测试过这些代码,因此您可能需要修复一些我错过的语法错误。