ViewGroup的dispatchDraw()方法的疑惑

/ android / 1 条评论 / 2177浏览

view

前言

这篇文章是记录自己遇到的一个问题以及对这个问题的一些思考,所以其中关于View绘制流程相关的内容有可能存在错误。

问题的产生

BGASwipeBackLayout-Android 这个git库的commit ID "9a82cd25b8e7f087035afd5ed2db101ad293aabb" 到 "85360541cdc610266c50c2c46f67784a08a19ad1"之间的提交是为了解决“修复非透明主题模式滑动返回结束时闪屏”这个问题,其中的关键是在cn/bingoogolapple/swipebacklayout/BGASwipeBackShadowView.java中用到了dispatchDraw()这个方法。

@Override
protected void dispatchDraw(Canvas canvas) {
    super.dispatchDraw(canvas);
    if (mIsTranslucent) {
        return;
    }

    if (mPreContentView == null && mPreDecorView != null) {
        // TODO 处理部分 View 多次 draw 时会卡死
        mPreDecorView.draw(canvas);
    }
}

最最起作用的是"mPreDecorView.draw(canvas);"这句话,这句代码的意思是将前一个activity界面中的DecorView绘制到当前activity中的画布上。正因为有了这个操作那么activity界面切换的时候闪屏就没有了。因为BGASwipeBackShadowView是跟随着手指将当前activity界面从左向右滑动,其中所有的view都向右移动,当整个界面的移动完以后松开手指此时界面将触发dispatchDraw()这个方法。我的问题是即使在界面销毁前我在dispatchDraw()中调用某个View.draw()方法,让View的内容显示在当前BGASwipeBackShadowView的画布(Canvas)上,但是最终这个activity还是会销毁,销毁切换到上一个activity时不应该还是有一个切换的瞬间吗?

问题的思索

1.什么时候调用dispatchDraw()方法呢? View组件的绘制会调用draw(Canvas canvas)方法。draw过程中主要是画Drawable背景,画完背景后draw过程会调用onDraw(Canvas canvas)方法,然后就是dispatchDraw(Canvas canvas)方法。dispatchDraw()主要是分发给子组件进行绘制,我们通常自定义view的时候重写的是onDraw()方法。 值得注意的是ViewGroup容器组件的绘制,当它没有背景时直接调用的是dispatchDraw()方法, 而不会调用draw()方法。当它有背景的时候就调用draw()方法,而draw()方法里包含了dispatchDraw()方法的调用。因此要在ViewGroup上绘制东西的时候往往重写的是dispatchDraw()方法而不是onDraw()方法。

2.当两个standard activity处于同一个activity stack中,此时A处于onStop状态,B处于onResume状态,当B返回到A时,状态是怎样执行的? 测试结果:B onPause->A onStart->A onResume->B onStop->B onDestroy

问题结论?

在我当前这个问题中是activit B中BGASwipeBackShadowView的dispatchDraw()方法先执行,那么它就会将activity A中的DecorView绘制到当前activity B界面上。接着B进入onPause,此时界面上仍然显示的是B的内容。再接着进入A onStart,此时系统准备A的界面,将A中的DecorView重新绘制到当前A界面中。下来进入A onResume,此时屏幕上显示A的界面,同时隐藏B的界面。因为A界面和B界面是同样的内容,所以屏幕的显示不会有明显的切换效果。 上面的“结论”只是自己的猜测,等待以后的验证。 关于手机屏幕的显示与应用程序生命周期相关的内容看来要学些了......(未完待续)

  1. 目前主要疑惑的是手机屏幕上图像的绘制与Activity的生命周期存在何种关系。

    回复