什么导致View的OnDraw方法被调用,以及何时被调用?

7
我在安卓的Textview类中看到了这个:
@Override
protected void onDraw(Canvas canvas) {
    restartMarqueeIfNeeded();

    // Draw the background for this view
    super.onDraw(canvas);

在Android的View类中,我发现它是空的:
/**
 * Implement this to do your drawing.
 *
 * @param canvas the canvas on which the background will be drawn
 */
protected void onDraw(Canvas canvas) {
}

如果超类的方法为空,为什么还要调用它呢?

带参数canvas的方法在哪里被调用了?

参数canvas是由安卓系统自动传递的吗?

ondraw方法是由谁何时调用的?

当被重写时,子类的方法会代替超类的方法被调用吗?

这是我的自定义视图示例:

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));


    }
}
class MyView extends View {


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

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
}

谁调用了MyView.OnDraw方法?

肯定有一行代码调用了MyView.OnDraw方法,不是吗?


1
onDraw方法中使用Thread#dumpStack(),并查看logcat - pskink
可能是Android when onDraw is called?的重复问题。 - user1643723
3个回答

3
回答您的问题:
为什么有人会调用超类的方法,如果它是空的?
因为如果您不确定实现方式,调用super是一个好习惯。例如,如果您扩展了库中的类的扩展类,并且没有该代码,则应调用超级方法。在这种情况下,这并不是必要的,但我建议这样做。
方法被带有参数canvas的谁调用?
我不完全确定您的意思,但当您让您的类覆盖View时,您可以覆盖onDraw,以便您可以决定您的视图如何显示
android系统是否自动传递参数画布?
是的
ondraw方法由谁何时调用?
当Activity第一次变得可见时,它将被连接到其生命周期的Activity调用。您不必担心这个。当您在View上调用invalidate或者它被视为脏(需要重新绘制)时,也会调用它。在您的示例中,ondraw将被调用,但由于您没有在提供的画布上绘制任何内容,因此您不会在Activity上看到任何内容。如果您向该函数添加一些日志,则将在logcat中看到它过来
当它被覆盖时,子类的方法是否而非超类的方法被调用?
是的,这就是扩展类和重写方法的工作方式

我已经更新了我的问题。我的问题是:谁调用了MyView.OnDraw方法?因为我只看到Myview类的对象被创建,然后调用构造函数。 - user5949689
"setContentView(new MyView(this));" 然后: "public MyView(Context context) { super(context); }" - user5949689
在代码中肯定有一行调用了Myview.Ondraw方法的代码,对吧? - user5949689

1

onDraw方法是在ViewRoot接收到某个子视图的invalidatepostInvalidateOnAnimation请求后被调用。ViewRoot会调用每个Window子视图的onDraw,然后这些子视图又会绘制它们可见的子视图(对于ViewGroup)或者自身(对于Views),直到最后一个视图被绘制。

绘制可以在主线程的任何时候进行,这在旧版本中是默认的,但不是视觉上完美的。或者可以通过Choreographer延迟到下一个垂直同步。现代Android版本通过Choreographer调度所有由无效和Drawable动画引起的onDraw调用。

Canvas由SurfaceFlinger提供,它是Android窗口系统,内部使用OpenGL ES和硬件合成来管理显示的窗口。

当它被覆盖时,子类的方法是否会代替父类的方法被调用?

是的。但通常不调用超类的onDraw方法并不是一个有效的策略(为什么你首先要子类化它?!)如果你不想绘制任何东西,可以调用setWillNotDraw(true)(顺便说一下,基础View类的默认值已经是true)。

0

除了以上内容之外:调整窗口大小以合理地适应“键盘”后,软键盘会导致 View.invalidate()-->View.onDraw() 序列。自定义的 View.onDraw() 必须保持自身状态以预期这种可能性。
这可能解释了为什么在配备蓝牙键盘的平板电脑上开发和测试的应用在现实世界中表现出意外行为。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接