View 的 Detach 状态对动画的影响
起因是在用外部是 ViewPager2
实现的 banner 控件时,每个 View
有浮动的动画成果,在滑动切换后,动画隐没。咱们都晓得 ViewPager2
的外部是用 RecyclerView
来实现的,而 RecyclerView
复用和回收 View
时会将 View
增加和移除,第一想法是 Detach
对动画有影响,在试验过这个想法,开始剖析
切入点
startAnimation
、dispatchDetachedFromWindow
源码剖析
startAnimation
public void startAnimation(Animation animation) {animation.setStartTime(Animation.START_ON_FIRST_FRAME);
setAnimation(animation);
invalidateParentCaches();
invalidate(true);
}
public void setAnimation(Animation animation) {
mCurrentAnimation = animation;
...
}
能够看到只是简略给 mCurrentAnimation
进行了赋值,其余都是动画相干的设置,而后执行了 invalidate
,那么动画是怎么被执行的呢?猜想onDraw
里必定有猫腻,咱们再看看另一个切入点
dispatchDetachedFromWindow
void dispatchDetachedFromWindow() {
...
onDetachedFromWindowInternal();
...
if (listeners != null && listeners.size() > 0) {
...
// 分发给内部回调
for (OnAttachStateChangeListener listener : listeners) {listener.onViewDetachedFromWindow(this);
}
}
...
mAttachInfo = null;
if (mOverlay != null) {
// 分发给 Overlay
mOverlay.getOverlayView().dispatchDetachedFromWindow();
}
notifyEnterOrExitForAutoFillIfNeeded(false);
}
protected void onDetachedFromWindowInternal() {
...
mCurrentAnimation = null;
...
}
只是简略的将 mCurrentAnimation
置为 null
,onDraw
的嫌疑更大了,咱们追踪 mCurrentAnimation
的usage
,发现在 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime)
中有应用,那也根本确定了咱们的猜想
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
...
final Animation a = getAnimation();
if (a != null) {more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
...
} else {...}
return more;
}
private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
Animation a, boolean scalingRequired) {
...
if (!initialized) {
...
onAnimationStart();}
...
return more;
}
看到 onAnimationStart
咱们就能够确定了,动画的确是通过 onDraw
来执行的,detached
后,获取不到动画,也就进行了。但具体动画是怎么执行的不在探讨范畴内。