开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情
dispatchDraw
- dispatchDraw最后一段
// 由于child.draw 会调用parent的mGroupFlags设置一些参数,所以重新更新一下flags
//由于 mGroupFlags是protected类型的,又因为view和viewGroup都在同一包中,所以view中可以获取到mGroupFlags,并对其修改。
flags = mGroupFlags;
//view.draw会调用这个函数applyLegacyAnimation,这个函数可能会导致这里flags设置为FLAG_INVALIDATE_REQUIRED
if ((flags & FLAG_INVALIDATE_REQUIRED) == FLAG_INVALIDATE_REQUIRED) {
invalidate(true);
}
//调用动画监听器
if ((flags & FLAG_ANIMATION_DONE) == 0 && (flags & FLAG_NOTIFY_ANIMATION_LISTENER) == 0 &&
mLayoutAnimationController.isDone() && !more) {
mGroupFlags |= FLAG_NOTIFY_ANIMATION_LISTENER;
final Runnable end = new Runnable() {
@Override
public void run() {
//通知animationListener
notifyAnimationListener();
}
};
post(end);
}
post
public boolean post(Runnable action) {
.....
return attachInfo.mHandler.post(action);
.....
我们通过post的源码可以看出来post是通过handler机制发生的。 这个attachInfo是view里面的静态类,也就说同一个activity里面的view的attachInfo都是同一个。 attachInfo是在ViewRootImpl的构造函数里面创建的。
其中attachInfo.mHandler = new ViewRootImpl.ViewRootHandler()
post(Runnable) 是不会走handleMessage的(这里的post(end)就是这样),而是直接调用Runnable.run()方法,当然这会发生在Looper绑定的线程中。
draw(Canvas canvas, ViewGroup parent, long drawingTime) 这个函数也挺长的
- 第一段
//canvas.isHardwareAccelerated可以判断该canvas是否启用硬件加速
//默认支持硬件加速,硬件加速时这里的canvas是canvas的子类:DisplayListCanvas
final boolean hardwareAcceleratedCanvas = canvas.isHardwareAccelerated();
//当view没有deattch,开启了硬件加速,这会是true
boolean drawingWithRenderNode = mAttachInfo != null
&& mAttachInfo.mHardwareAccelerated
&& hardwareAcceleratedCanvas;
//是否执行了invalidate
boolean more = false;
硬件加速知识:
在硬件加速中,每一个view中保存着一个renderNode,由它代表当前view在硬件加速中的形象
每一种绘制操作由的DisplayListOp表示
view.updateDisplayListIfDirty方法会收集当前view所需的绘制内容,这个方法还会执行dispatchGetDisplayList()来调用子view的updateDisplayListIfDirty方法。
2.
Transformation transformToApply = null;
boolean concatMatrix = false;
//指示是否处于兼容模式
final boolean scalingRequired = mAttachInfo != null && mAttachInfo.mScalingRequired;
..........
RenderNode renderNode = null;
Bitmap cache = null;
int layerType = getLayerType();
//启动了软件绘制
if (layerType == LAYER_TYPE_SOFTWARE || !drawingWithRenderNode) {
if (layerType != LAYER_TYPE_NONE) {
//没有指定硬件绘制,那么就是软件绘制
layerType = LAYER_TYPE_SOFTWARE;
buildDrawingCache(true);
}
cache = getDrawingCache(true);
}
//硬件绘制
if (drawingWithRenderNode) {
//更新displaylist,如果renderNode失效递归调用view,更新displaylist
renderNode = updateDisplayListIfDirty();
//renderNode有效
if (!renderNode.isValid()) {
renderNode = null;
drawingWithRenderNode = false;
}
}
..............
//drawingWithDrawingCache = cache != null && !drawingWithRenderNode;
if (!drawingWithDrawingCache) {//硬件绘制或者软件绘制的cache为空
//硬件绘制
if (drawingWithRenderNode) {
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
((DisplayListCanvas) canvas).drawRenderNode(renderNode);
} else {
// 软件绘制
//PFLAG_SKIP_DRAW指示是否跳过当前帧的绘制
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
//draw()方法里面是否绘制涉及到的判断和PFLAG_DIRTY_MASK有关
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
//分发子view绘制
dispatchDraw(canvas);
} else {
//绘制自己
draw(canvas);
}
}
} else if (cache != null) {//软件绘制且存在cache
mPrivateFlags &= ~PFLAG_DIRTY_MASK;
if (layerType == LAYER_TYPE_NONE || mLayerPaint == null) {
Paint cachePaint = parent.mCachePaint;
if (cachePaint == null) {
cachePaint = new Paint();
cachePaint.setDither(false);
parent.mCachePaint = cachePaint;
}
cachePaint.setAlpha((int) (alpha * 255));
//绘制缓存
canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
} else {
int layerPaintAlpha = mLayerPaint.getAlpha();
if (alpha < 1) {
mLayerPaint.setAlpha((int) (alpha * layerPaintAlpha));
}
canvas.drawBitmap(cache, 0.0f, 0.0f, mLayerPaint);
if (alpha < 1) {
//绘制缓存
mLayerPaint.setAlpha(layerPaintAlpha);
}
}
}