滚动我的自定义组件时GC滞后应用程序

时间:2014-07-16 20:20:30

标签: java android garbage-collection

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

Screenshot

当我在该表上向上或向下滚动时,会出现问题。有时它会正确滚动,而在其他情况下则需要延迟。在logcat中,我意识到GC启动时会出现延迟。

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投入使用时不会出现这些滞后?

提前致谢并抱歉英语不好。

2 个答案:

答案 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));

请注意,我还没有编译或测试过这些代码,因此您可能需要修复一些我错过的语法错误。