Java 当滚动我的自定义组件时,应用程序
我必须创建一个自定义组件(我不能使用gridview或dataTable),这是一个包含6列和X行(没有图像)的表。下图显示它正在工作: 当我在那张桌子上向上或向下滚动时,问题就出现了。有时它会正确滚动,而在另一些情况下则会延迟。在logcat中,我意识到当GC启动时会出现延迟 我一直在寻找一种优化我的组件的方法,但是我对Java还是新手。我读过关于优化视图和重用对象的文章。下面是我当前的getView代码:Java 当滚动我的自定义组件时,应用程序,java,android,garbage-collection,Java,Android,Garbage Collection,我必须创建一个自定义组件(我不能使用gridview或dataTable),这是一个包含6列和X行(没有图像)的表。下图显示它正在工作: 当我在那张桌子上向上或向下滚动时,问题就出现了。有时它会正确滚动,而在另一些情况下则会延迟。在logcat中,我意识到当GC启动时会出现延迟 我一直在寻找一种优化我的组件的方法,但是我对Java还是新手。我读过关于优化视图和重用对象的文章。下面是我当前的getView代码: @Override public
@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;
}
}
@覆盖
公共视图getView(int位置、视图转换视图、视图组父视图){
if(null==this.parent)
this.parent=(ListViewOT)父对象;
if(this.parent.isInEditMode()){
super.getView(position、convertView、parent);
}
mActivity=(MainActivity)parent.getContext();
this.c=this.getCursor();
c、 移动位置(位置);
if(null==convertView){
视图=(LinearLayout)LinearLayout.inflate(
this.context,R.layout.item_lvacos,null);
行=(LinearLayout)视图。getChildAt(1);
headerRow=(TableRow)this.parent.getHeader().getChildAt(0);
for(int j=0;j 否则如果(cell_width我相信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;
在这个类中的某个地方加载可绘图项(在构造函数中或在onfinishflate
中通常是我的选择):
移除这些(您有两次):
替换为:
column.setBackgroundDrawable(getMyBackgroundDrawable (status));
请注意,我还没有编译或测试过这些代码,所以您可能需要修复我遗漏的一些语法错误。伙计,我只是在看这篇文章和您的其他文章时有些畏缩。让我们尝试一下您所拥有的。您在确定宽度方面有一些非常复杂的算法,但在我们解决这些问题之前,我们肯定可以加快速度p、 我将对您应该做的做一个更高的概述。您必须将其转换为代码,因为这是一个复杂的问题
您需要创建一个缓存,给定一个位置和一列#来存储测量的宽度。始终首先检查缓存,只有在没有找到任何内容时才进行测量。getView()
方法可以在每个位置调用3-4次。因此,这应该会产生巨大的改进
另一种方法是,如果你有大量的动态文本或重复文本,你可以根据文本创建缓存。因此,对于给定的字符串,你可以缓存测量的宽度
假设您只在列中显示文本,有一种替代测量解决方案可能会更快。只需使用TextView的getPaint()。measureText(字符串)
method。它将以像素为单位返回文本的宽度。您可能需要添加一些绒毛,比如额外的4-8 dp,但这可能比您正在做的更快
缓存示例:
在适配器的构造函数中,执行以下操作:
Map<String, Float> mWidthCache = new HashMap<String, Float>();
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) 为什么不能使用列表视图来进行此操作?(2)我不认为GC会让你慢下来,我认为滚动表视图的使用会慢下来。如果你可以使用列表视图
或其他一些优化的结构来回收视图,它可能会更平滑。你好Kibler88。谢谢你的帮助。我按照你的建议做了,但结果仍然一样。还有什么我可以做的吗?你好Jay。我不知道如何缓存位置。你能帮我多一点吗?使用简单缓存示例更新OK。这个解决方案似乎是正确的。但我无法实现它。正如我之前所说,我是Android新手,显示的功能比你的示例复杂得多。但无论如何,谢谢你。。。
Map<String, Float> mWidthCache = new HashMap<String, Float>();
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