尽管有视图层次结构,但调用TextView.setText()会重绘整个屏幕

时间:2013-01-08 19:10:13

标签: android android-layout textview

在我的应用程序中,我有一个时间显示,每秒更新一次。每次用于秒字段的TextView更改时,Developer Options-> Show surface updates工具都会闪烁整个屏幕。我环顾四周,真的只能找到this question,这很好地说明了没有办法阻止TextView导致至少部分窗口重新布局。所以我肯定要验证我的TextView是否包装在他们自己的容器中,但我仍然有同样的问题。每次调用setText()都会导致整个视图闪烁。

我的层次结构如下:

  • 片段
    • RelativeLayout(片段根视图)
      • 的LinearLayout
        • RelativeLayout的
          • 我的时间TextViews
      • 很少变化的各种其他视图组件

如果可能,我想解决这个问题。如果可能的话,我确实需要尝试减少我的观看次数,我打算继续努力,但这仍然是我想从应用中删除的问题。

2 个答案:

答案 0 :(得分:10)

当硬件加速打开时,显示曲面更新会闪烁整个屏幕,但这并不意味着整个窗口被重绘。您可以使用另一个选项,它可以显示硬件加速打开时屏幕的哪些部分被重新绘制(“显示GPU视图更新”)。

答案 1 :(得分:1)

我遇到了类似的问题,我正在更新一个定时器,每次都会导致测量通过。如果你有一些很难测量的东西,比如ListView,它会影响性能。在我的情况下,我有一个ListView在更新定时器时不需要更改大小,因此我创建了一个自定义ListView持有者来阻止该度量从级联到ListView。现在它运行顺利!

public class CustomListviewHolderLayout extends FrameLayout {

    public int currentWidth = 0;
    public int currentHeight = 0;

    public CustomListviewHolderLayout(Context context) {
        super(context);
    }

    public CustomListviewHolderLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomListviewHolderLayout(Context context, AttributeSet attrs,
            int defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
        //Debug Prints
        String wMode = "";
        switch(MeasureSpec.getMode(widthMeasureSpec)){
            case MeasureSpec.AT_MOST:
                wMode = "AT_MOST"; break;
            case MeasureSpec.EXACTLY:
                wMode = "EXACTLY"; break;
            case MeasureSpec.UNSPECIFIED:
                wMode = "UNSPECIFIED"; break;
            default:
                wMode = "";
        }
        String hMode = "";
        switch(MeasureSpec.getMode(heightMeasureSpec)){
            case MeasureSpec.AT_MOST:
                hMode = "AT_MOST"; break;
            case MeasureSpec.EXACTLY:
                hMode = "EXACTLY"; break;
            case MeasureSpec.UNSPECIFIED:
                hMode = "UNSPECIFIED"; break;
            default:
                hMode = "";
        }
        Log.i("RandomCustomListViewHolder", "wMode = " + wMode + ", size = " + MeasureSpec.getSize(widthMeasureSpec));
        Log.i("RandomCustomListViewHolder", "hMode = " + hMode + ", size = " + MeasureSpec.getSize(heightMeasureSpec));
        //only remeasure child listview when the size changes (e.g. orientation change)
        if(getChildCount() == 1){
            if(((MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.EXACTLY) ||
                (MeasureSpec.getMode(widthMeasureSpec) == MeasureSpec.AT_MOST))
              &&((MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.EXACTLY) ||
                (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST))){
                //check if height dimensions are different than before
                int newWidth =  MeasureSpec.getSize(widthMeasureSpec);
                int newHeight = MeasureSpec.getSize(heightMeasureSpec);
                if((newWidth != currentWidth) || (newHeight != currentHeight)){
                    //remeasure if different
                    Log.i("RandomCustomListViewHolder", "measuring listView");
                    View childView = getChildAt(0);
                    childView.measure(widthMeasureSpec, heightMeasureSpec);
                    currentWidth = newWidth;
                    currentHeight = newHeight;
                    this.setMeasuredDimension(newWidth, newHeight);
                } else {
                    //still set this view's measured dimension
                    this.setMeasuredDimension(newWidth, newHeight);     
                }               
            } else {
                //Specify match parent if one of the dimensions is unspecified
                this.setMeasuredDimension(ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT);                   
            }
        } else {
            //view does not have the listview child, measure normally 
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);           
            currentWidth = 0;
            currentHeight = 0;
        }
    }
}