【问题标题】:Does View.setVisibility(View.VISIBLE) forces the view to redraw even if it's already visible?View.setVisibility(View.VISIBLE) 是否强制视图重绘,即使它已经可见?
【发布时间】:2013-10-06 13:15:15
【问题描述】:

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

【问题讨论】:

    标签: android optimization view


    【解决方案1】:

    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;
    }
    

    即使它(以某种方式)通过了那里,它也会检查各个标志的变化,并且仅在其中一个与原来不同时更新。

    【讨论】:

      【解决方案2】:

      查看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 将是假的,所以这不会做任何事情。

      但是,View#setVisible() 被以下内容覆盖:ImageViewMediaRouteButtonProgressBarSurfaceViewViewStub。您需要检查每个实现是否有其他额外功能 - 您可能正在使用这些子类之一。

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

      1. ClipDrawable
      2. 可绘制容器
      3. AnimationDrawable - 从 DrawableContainer 扩展
      4. InsetDrawable
      5. LayerDrawable
      6. RotateDrawble
      7. ScaleDrawable
      8. SlideDrawable

      根据您的组合,您可能会发现您实际上在做一些额外的事情,因此您需要调查您使用的是哪种View,以及它的背景可绘制对象是什么类型的可绘制对象。

      【讨论】:

        【解决方案3】:

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

        【讨论】:

        • 你能把源代码的链接贴出来吗(如果在互联网上可用)?
        • 例如这里link
        【解决方案4】:

        我不是 100%,但我不这么认为

        来自 View 类的 grepcode,这是来自 setFlags(int flags, int mask) 方法,该方法是从 setVisibility(int visibility) 调用的

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

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

        所以我会说不,它没有

        【讨论】:

          猜你喜欢
          • 2013-06-28
          • 2016-06-01
          • 1970-01-01
          • 2020-02-15
          • 1970-01-01
          • 1970-01-01
          • 2011-10-23
          • 2011-10-19
          • 1970-01-01
          相关资源
          最近更新 更多