【问题标题】:Android when onDraw is called?调用onDraw时的Android?
【发布时间】:2014-02-17 01:44:00
【问题描述】:

据说调用invalidate()时会调用onDraw()。但是,当我查看 android 源代码时。我没有找到在 invalidate() 中调用 onDraw() 的位置。所以我仍然对如何为视图调用 onDraw() 方法感到困惑。谁能帮我解决这个问题?

【问题讨论】:

  • “据说”是谁说的?你能提供一个指向你的来源的链接吗?
  • @Monad:我在其他答案中看到过,但这或多或少是一种误解。从功能上讲,当调用 'invalidate()' 时, onDraw '将被调用'。只是'invalidate()'不会直接调用onDraw()。
  • @DeeV 是的,我意识到这一点并赞成您的回答。我要求 OP 提供声明的来源。
  • 我不记得确切的位置。但我相信我已经看过很多次了。
  • @MonadNewb 我认为这个答案有点误导:stackoverflow.com/questions/11912406/…

标签: android


【解决方案1】:

Invalidate 不会直接调用onDraw()。它为系统安排了一次绘制通道,表示视图需要在未来的某个时间点进行绘制,这通常几乎是立即进行。如果 UI 线程被阻塞,则可能需要一些时间。

【讨论】:

    【解决方案2】:

    绘图

    通过遍历树并渲染与无效区域相交的每个视图来处理绘图。因为树是按顺序遍历的,这意味着父母将在他们的孩子之前(即之后)绘制,兄弟姐妹按照它们在树中出现的顺序绘制。如果您为 View 设置了背景可绘制对象,则 View 将在回调其 onDraw() 方法之前为您绘制它。 请注意,框架不会绘制不在无效区域中的视图。 要强制绘制视图,请调用invalidate()

    使整个视图无效。 如果视图可见,onDraw(android.graphics.Canvas) 将在未来的某个时间点被调用。这必须从 UI 线程调用。要从非 UI 线程调用,请调用 postInvalidate()

    10340    public void invalidate() {
    10341        invalidate(true);
    10342    }
    

    来源

    http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.2.2_r1/android/view/View.java#View.invalidate%28boolean%29

    这是 invalidate() 工作实际发生的地方。完整的 invalidate() 会导致绘图缓存失效,但可以在 invalidateCache 设置为 false 的情况下调用此函数,以在不需要它的情况下跳过该失效步骤(例如,与相同的内容)。

    参数:

    invalidateCache 此视图的绘图缓存是否也应失效。这对于完全无效通常为 true,但如果 View 的内容或尺寸未更改,则可能设置为 false。

    10354
    10355    void invalidate(boolean invalidateCache) {
    10356        if (skipInvalidate()) {
    10357            return;
    10358        }
    10359        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
    10360                (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
    10361                (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
    10362            mLastIsOpaque = isOpaque();
    10363            mPrivateFlags &= ~PFLAG_DRAWN;
    10364            mPrivateFlags |= PFLAG_DIRTY;
    10365            if (invalidateCache) {
    10366                mPrivateFlags |= PFLAG_INVALIDATED;
    10367                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
    10368            }
    10369            final AttachInfo ai = mAttachInfo;
    10370            final ViewParent p = mParent;
    10371            //noinspection PointlessBooleanExpression,ConstantConditions
    10372            if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
    10373                if (p != null && ai != null && ai.mHardwareAccelerated) {
    10374                    // fast-track for GL-enabled applications; just invalidate the whole hierarchy
    10375                    // with a null dirty rect, which tells the ViewAncestor to redraw everything
    10376                    p.invalidateChild(this, null);
    10377                    return;
    10378                }
    10379            }
    10380
    10381            if (p != null && ai != null) {
    10382                final Rect r = ai.mTmpInvalRect;
    10383                r.set(0, 0, mRight - mLeft, mBottom - mTop);
    10384                // Don't call invalidate -- we don't want to internally scroll
    10385                // our own bounds
    10386                p.invalidateChild(this, r);
    10387            }
    10388        }
    10389    }
    

    【讨论】:

    • 我想这就是我想要的答案。我注意到在我没有在此处发布的代码中,有时在我调用 invalidate() 之后不会调用 onDraw()。我认为可能会跳过 invalidate() ,因为没有什么可以改变的。
    • 如果您致电invalidate,它将刷新您的视图。我不认为它会跳过。如果您想确保可以在onDraw 中记录一些信息并致电invalidate。您将看到日志消息。如果没有变化,您不会注意到它,但我认为您的视图已刷新。没有变化并不意味着跳过。
    • 我注意到我失效的组件在视图父级之外。我认为这就是为什么不调用 onDraw 的原因。
    【解决方案3】:

    我必须调用 setWillNotDraw(false)。 ViewGroup 的所有子类默认设置为 true。

    【讨论】:

      【解决方案4】:

      看看这个post。这准确地解释了何时调用 onDraw()。

      【讨论】:

        【解决方案5】:

        根据View | Android Developers

        通过遍历树并渲染每个视图来处理绘图 与无效区域相交。因为树是按顺序遍历的, 这意味着父母会在他们的前面(即后面)画 孩子,兄弟姐妹按照它们在树中出现的顺序绘制。如果 你为一个视图设置了一个可绘制的背景,然后视图将绘制它 在回调它的 onDraw() 方法之前为你准备。

        请注意,框架不会绘制不在 无效区域。

        要强制绘制视图,请调用 invalidate()。

        这意味着当 UI 线程到达它(无效区域)时,它将为该区域调用 onDraw()。

        【讨论】:

          【解决方案6】:

          视图的 onDraw() 在以下情况下被调用:

          1. 最初绘制视图
          2. 每当在视图上调用 invalidate()

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-02-02
            相关资源
            最近更新 更多