View.setVisibility(View.VISIBLE)是否强制视图重绘,即使它已经可见?

时间:2013-09-30 15:35:27

标签: android optimization view

我正在尝试找出自定义视图的优化。我想知道调用View.setVisibility(View.VISIBLE)是否强制Android框架更新视图可见性(< - 强制视图重绘),即使视图已经可见。

4 个答案:

答案 0 :(得分:5)

No, it doesn't.

看看setVisibility()

public void setVisibility(int visibility) {
    setFlags(visibility, VISIBILITY_MASK);
    if (mBGDrawable != null) mBGDrawable.setVisible(visibility == VISIBLE, false);
}

它只是调用setFlags(),如果没有任何变化,它会立即返回:

....
int changed = mViewFlags ^ old;
if (changed == 0) {
    return;
}

即使它(以某种方式)过去了,它也会检查各个标志是否发生变化,只有当其中一个标志与其不同时才会更新。

答案 1 :(得分:3)

查看View#setVisibility

public void setVisibility(int visibility) {
    setFlags(visibility, VISIBILITY_MASK);
    if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
}

setFlags(...)方法以:

开头
int old = mViewFlags;
mViewFlags = (mViewFlags & ~mask) | (flags & mask);

int changed = mViewFlags ^ old;
if (changed == 0) {
    return;
}

所以我很确定这种方法没有做任何事情。否则,它会做很多事情,除了触发布局和重绘。

Background#setVisible类似:

public boolean setVisible(boolean visible, boolean restart) {
    boolean changed = mVisible != visible;
    if (changed) {
        mVisible = visible;
        invalidateSelf();
    }
    return changed;
}

if将为false,因此不会执行任何操作。

但是,View#setVisible()会被ImageViewMediaRouteButtonProgressBarSurfaceViewViewStub覆盖。如果它还有其他任何额外的东西,您需要检查每个实现 - 您可能正在使用其中一个子类。

同样适用于Drawable:有8个类覆盖Drawable#setVisible(boolean, boolean)

  1. ClipDrawable
  2. DrawableContainer
  3. AnimationDrawable - 从DrawableContainer扩展
  4. InsetDrawable
  5. LayerDrawable
  6. RotateDrawble
  7. ScaleDrawable
  8. SlideDrawable
  9. 根据您的组合,您可能会发现您实际上正在做一些额外的事情,因此您需要调查您正在使用的View类型及其背景可绘制的内容。

答案 2 :(得分:1)

setVisibility()通过调用setFlags里面设置视图标志..如果我们进入sdk View.setFlags(),我们可以看到如果标志状态没有改变,这个方法无关。来自sdk的代码View.setFlags()方法:int changed = mViewFlags ^ old; if (changed == 0) { return; }

答案 3 :(得分:1)

我不是100%,但我不相信

来自View类的grepcode,这是来自setFlags(int flags, int mask)

调用的setVisibility(int visibility)方法
int changed = mViewFlags ^ old;
if (changed == 0) {
    return;
}

之后在同一方法中调用requestLayout()invalidate()

所以,我会说不,它不会