Java 当滚动我的自定义组件时,应用程序

Java 当滚动我的自定义组件时,应用程序,java,android,garbage-collection,Java,Android,Garbage Collection,我必须创建一个自定义组件(我不能使用gridview或dataTable),这是一个包含6列和X行(没有图像)的表。下图显示它正在工作: 当我在那张桌子上向上或向下滚动时,问题就出现了。有时它会正确滚动,而在另一些情况下则会延迟。在logcat中,我意识到当GC启动时会出现延迟 我一直在寻找一种优化我的组件的方法,但是我对Java还是新手。我读过关于优化视图和重用对象的文章。下面是我当前的getView代码: @Override public

我必须创建一个自定义组件(我不能使用gridview或dataTable),这是一个包含6列和X行(没有图像)的表。下图显示它正在工作:

当我在那张桌子上向上或向下滚动时,问题就出现了。有时它会正确滚动,而在另一些情况下则会延迟。在logcat中,我意识到当GC启动时会出现延迟

我一直在寻找一种优化我的组件的方法,但是我对Java还是新手。我读过关于优化视图和重用对象的文章。下面是我当前的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;
                }
            }
@覆盖
公共视图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