当前位置:网站首页>ViewRootImpl和WindowManagerService笔记
ViewRootImpl和WindowManagerService笔记
2022-07-05 20:47:00 【全栈程序员站长】
大家好,又见面了,我是全栈君,今天给大家准备了Idea注册码。
1、每个窗体的ViewRootImpl都有一个mWindowAttributes窗体属性,该属性在WindowManagerGlobal.updateViewLayout()->ViewRootImpl.setView()和WindowManagerGlobal.updateViewLayout->ViewRootImpl.setLayoutParams()中赋值。同一时候ViewRootImpl.mWindowAttributesChanged也会设为true表示窗体属性已更改。当窗体属性更改时。surfaceChanged也会设置为true
if (mWindowAttributesChanged) {
mWindowAttributesChanged = false;
surfaceChanged = true;
params = lp;
}
当surfaceChanged设置为true时,以下这段代码会调用
if (surfaceChanged) {
mSurfaceHolderCallback.surfaceChanged(mSurfaceHolder,
lp.format, mWidth, mHeight);
SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
if (callbacks != null) {
for (SurfaceHolder.Callback c : callbacks) {
c.surfaceChanged(mSurfaceHolder, lp.format,
mWidth, mHeight);
}
}
}
调用回调函数,表明当前窗体Surface有更新。
2、在WMS中Stackbox、TaskStack、Task、AppWindowToken之间的关系:
3、relayoutWindow()函数中对于可见的壁纸、输入法、activity等窗体会作下面处理:
if (viewVisibility == View.VISIBLE &&
(win.mAppToken == null || !win.mAppToken.clientHidden)) {
toBeDisplayed = !win.isVisibleLw();
if (win.mExiting) {
winAnimator.cancelExitAnimationForNextAnimationLocked();
win.mExiting = false;
}
if (win.mDestroying) {
win.mDestroying = false;
mDestroySurface.remove(win);
}
if (oldVisibility == View.GONE) {
winAnimator.mEnterAnimationPending = true;
}
if (toBeDisplayed) {
if (win.isDrawnLw() && okToDisplay()) {
winAnimator.applyEnterAnimationLocked();
}
if ((win.mAttrs.flags
& WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON) != 0) {
if (DEBUG_VISIBILITY) Slog.v(TAG,
"Relayout window turning screen on: " + win);
win.mTurnOnScreen = true;
}
if (win.isConfigChanged()) {
if (DEBUG_CONFIGURATION) Slog.i(TAG, "Window " + win
+ " visible with new config: " + mCurConfiguration);
outConfig.setTo(mCurConfiguration);
}
}
if ((attrChanges&WindowManager.LayoutParams.FORMAT_CHANGED) != 0) {
// To change the format, we need to re-build the surface.
winAnimator.destroySurfaceLocked();
toBeDisplayed = true;
surfaceChanged = true;
}
try {
if (!win.mHasSurface) {
surfaceChanged = true;
}
SurfaceControl surfaceControl = winAnimator.createSurfaceLocked();
if (surfaceControl != null) {
outSurface.copyFrom(surfaceControl);
if (SHOW_TRANSACTIONS) Slog.i(TAG,
" OUT SURFACE " + outSurface + ": copied");
} else {
// For some reason there isn't a surface. Clear the
// caller's object so they see the same state.
outSurface.release();
}
} catch (Exception e) {
mInputMonitor.updateInputWindowsLw(true /*force*/);
Slog.w(TAG, "Exception thrown when creating surface for client "
+ client + " (" + win.mAttrs.getTitle() + ")",
e);
Binder.restoreCallingIdentity(origId);
return 0;
}
if (toBeDisplayed) {
focusMayChange = isDefaultDisplay;
}
if (win.mAttrs.type == TYPE_INPUT_METHOD
&& mInputMethodWindow == null) {
mInputMethodWindow = win;
imMayMove = true;
}
if (win.mAttrs.type == TYPE_BASE_APPLICATION
&& win.mAppToken != null
&& win.mAppToken.startingWindow != null) {
// Special handling of starting window over the base
// window of the app: propagate lock screen flags to it,
// to provide the correct semantics while starting.
final int mask =
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
| WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
| WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON;
WindowManager.LayoutParams sa = win.mAppToken.startingWindow.mAttrs;
sa.flags = (sa.flags&~mask) | (win.mAttrs.flags&mask);
}
}
假设当前窗体在退出(win.mExiting==true),就调用cancelExitAnimationForNextAnimationLocked()取消退出动画。假设窗体正在销毁(win.mDestroying)。就将该窗体从mDestroySurface中移除,mDestroySurface中保存的都是要销毁surface的窗体。假设该窗体上一个状态是不可见的,即由不可见进入可见状态,winAnimator.mEnterAnimationPending = true;表示等待进入动画;
void applyEnterAnimationLocked() {
final int transit;
if (mEnterAnimationPending) {
mEnterAnimationPending = false;
transit = WindowManagerPolicy.TRANSIT_ENTER;
} else {
transit = WindowManagerPolicy.TRANSIT_SHOW;
}
applyAnimationLocked(transit, true);
//TODO (multidisplay): Magnification is supported only for the default display.
if (mService.mDisplayMagnifier != null
&& mWin.getDisplayId() == Display.DEFAULT_DISPLAY) {
mService.mDisplayMagnifier.onWindowTransitionLocked(mWin, transit);
}
}
mEnterAnimationPending =true时。调用applyAnimationLocked()函数传进去的參数就为 WindowManagerPolicy.TRANSIT_ENTER表示窗体进入动画。
boolean applyAnimationLocked(int transit, boolean isEntrance) {
if (mLocalAnimating && mAnimationIsEntrance == isEntrance) {
// If we are trying to apply an animation, but already running
// an animation of the same type, then just leave that one alone.
return true;
}
// Only apply an animation if the display isn't frozen. If it is
// frozen, there is no reason to animate and it can cause strange
// artifacts when we unfreeze the display if some different animation
// is running.
if (mService.okToDisplay()) {
int anim = mPolicy.selectAnimationLw(mWin, transit);
int attr = -1;
Animation a = null;
if (anim != 0) {
a = anim != -1 ? AnimationUtils.loadAnimation(mContext, anim) : null;
} else {
switch (transit) {
case WindowManagerPolicy.TRANSIT_ENTER:
attr = com.android.internal.R.styleable.WindowAnimation_windowEnterAnimation;
break;
case WindowManagerPolicy.TRANSIT_EXIT:
attr = com.android.internal.R.styleable.WindowAnimation_windowExitAnimation;
break;
case WindowManagerPolicy.TRANSIT_SHOW:
attr = com.android.internal.R.styleable.WindowAnimation_windowShowAnimation;
break;
case WindowManagerPolicy.TRANSIT_HIDE:
attr = com.android.internal.R.styleable.WindowAnimation_windowHideAnimation;
break;
}
if (attr >= 0) {
a = mService.mAppTransition.loadAnimation(mWin.mAttrs, attr);
}
}
if (WindowManagerService.DEBUG_ANIM) Slog.v(TAG,
"applyAnimation: win=" + this
+ " anim=" + anim + " attr=0x" + Integer.toHexString(attr)
+ " a=" + a
+ " transit=" + transit
+ " isEntrance=" + isEntrance + " Callers " + Debug.getCallers(3));
if (a != null) {
if (WindowManagerService.DEBUG_ANIM) {
RuntimeException e = null;
if (!WindowManagerService.HIDE_STACK_CRAWLS) {
e = new RuntimeException();
e.fillInStackTrace();
}
Slog.v(TAG, "Loaded animation " + a + " for " + this, e);
}
setAnimation(a);
mAnimationIsEntrance = isEntrance;
}
} else {
clearAnimation();
}
return mAnimation != null;
}
applyAnimationLocked()函数中,对于状态栏、导航栏(三个虚拟按键)selectAnimationLw()返回相应的动画资源id,对于一般窗体返回0。对于一般应用窗体,有“窗体进入”动画、“窗体退出”动画、“窗体显示”动画、“窗体隐藏”动画。找到相应的窗体动画资源。然后调用mService.mAppTransition.loadAnimation(mWin.mAttrs, attr)进行载入动画。
载入成功后再调用setAnimation(a)来设置当前窗体动画。mAppTransition是一个AppTransition类对象,AppTransition是一个转场动画状态管理类,该类中有一个mAppTransitionState变量。该变量就是专门用来保存当前转场动画状态的;AppTransition类中有两个创建动画的函数,一个是创建放大动画createScaleUpAnimationLocked,一个是创建缩小动画createThumbnailAnimationLocked().
Animation loadAnimation(WindowManager.LayoutParams lp, int animAttr) {
int anim = 0;
Context context = mContext;
if (animAttr >= 0) {
AttributeCache.Entry ent = getCachedAnimations(lp);
if (ent != null) {
context = ent.context;
anim = ent.array.getResourceId(animAttr, 0);
}
}
if (anim != 0) {
return AnimationUtils.loadAnimation(context, anim);
}
return null;
}
该函数调用动画工具类AnimationUtils.loadAnimation()函数。參数anim是动画资源id,AnimationUtils.loadAnimation()中调用了createAnimationFromXml(context, parser);静态函数,parser是一个XmlResourceParser对象,动画资源id保存在该对象中。createAnimationFromXml()从名字能够看出就是从xml文件里解析出一个Animation出来
private static Animation createAnimationFromXml(Context c, XmlPullParser parser,
AnimationSet parent, AttributeSet attrs) throws XmlPullParserException, IOException {
Animation anim = null;
// Make sure we are on a start tag.
int type;
int depth = parser.getDepth();
while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
&& type != XmlPullParser.END_DOCUMENT) {
if (type != XmlPullParser.START_TAG) {
continue;
}
String name = parser.getName();
if (name.equals("set")) {
anim = new AnimationSet(c, attrs);
createAnimationFromXml(c, parser, (AnimationSet)anim, attrs);
} else if (name.equals("alpha")) {
anim = new AlphaAnimation(c, attrs);
} else if (name.equals("scale")) {
anim = new ScaleAnimation(c, attrs);
} else if (name.equals("rotate")) {
anim = new RotateAnimation(c, attrs);
} else if (name.equals("translate")) {
anim = new TranslateAnimation(c, attrs);
} else {
throw new RuntimeException("Unknown animation name: " + parser.getName());
}
if (parent != null) {
parent.addAnimation(anim);
}
}
return anim;
}
while循环依照一定的格式(动画格式)解析xml,依据不同的动画创建相应的Animation对象,然后返回。
对于AnimationSet动画(动画组合机制)。递归调用createAnimationFromXml()函数,将一个个动画按队列的方式保存,最后返回第一个动画。由源码看出android提供了组合动画、渐变动画、缩放动画、旋转动画、转场动画(移动的动画效果。图片浏览滑动效果)。
回到applyAnimationLocked()函数中。从xml文件里解析出一个相应的Animation后,再调用setAnimation(a)
public void setAnimation(Animation anim) {
if (localLOGV) Slog.v(TAG, "Setting animation in " + this + ": " + anim);
mAnimating = false;
mLocalAnimating = false;
mAnimation = anim;
mAnimation.restrictDuration(WindowManagerService.MAX_ANIMATION_DURATION);
mAnimation.scaleCurrentDuration(mService.mWindowAnimationScale);
// Start out animation gone if window is gone, or visible if window is visible.
mTransformation.clear();
mTransformation.setAlpha(mLastHidden ? 0 : 1); mHasLocalTransformation = true; }
该函数非常easy,设置mAnimating、mLocalAnimating为false,将上一步得到的Animation对象保存到WindowStateAnimator.mAnimation中。
3、WindowManagerService中 Configuration类对象mCurConfiguration中保存着当前配置信息。setNewConfiguration()负责更新这个对象。setNewConfiguration()被ActivityManagerService.updateConfigurationLocked()调用。AMS调用WMS的updateConfigurationLocked()函数时传入的configuration对象是AMS中的mConfiguration,那AMS与WMS保持相同configuration配置信息。
版权声明:本文博客原创文章,博客,未经同意,不得转载。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/117641.html原文链接:https://javaforall.cn
边栏推荐
- Is it safe to open an account online? Where can I get a low commission?
- Material Design组件 - 使用BottomSheet展现扩展内容(二)
- 研学旅游实践教育的开展助力文旅产业发展
- National Eye Care Education Conference, 2022 the Fourth Beijing International Youth eye health industry exhibition
- Applet event binding
- Abnova CRISPR spcas9 polyclonal antibody protocol
- Abnova丨 MaxPab 小鼠源多克隆抗体解决方案
- Applet global configuration
- 最长摆动序列[贪心练习]
- 3.3 project evaluation
猜你喜欢
Abnova丨E (DIII) (WNV) 重组蛋白 中英文说明书
小程序页面导航
Cutting edge technology for cultivating robot education creativity
Use of form text box (II) input filtering (synthetic event)
Prosci LAG-3 recombinant protein specification
Abbkine BCA法 蛋白质定量试剂盒说明书
MySQL fully parses json/ arrays
Abnova丨 MaxPab 小鼠源多克隆抗体解决方案
Abbkine丨TraKine F-actin染色试剂盒(绿色荧光)方案
AI automatically generates annotation documents from code
随机推荐
haas506 2.0开发教程 - 阿里云ota - pac 固件升级(仅支持2.2以上版本)
最长摆动序列[贪心练习]
Specification of protein quantitative kit for abbkine BCA method
Abnova fluorescent dye 620-m streptavidin scheme
重上吹麻滩——段芝堂创始人翟立冬游记
解析创客教育的知识迁移和分享精神
How to open an account online for futures? Is it safe?
Material Design组件 - 使用BottomSheet展现扩展内容(二)
Chemical properties and application instructions of prosci Lag3 antibody
NPDP如何续证?操作指南来了!
Ros2 topic [01]: installing ros2 on win10
10000+ 代码库、3000+ 研发人员大型保险集团的研发效能提升实践
Abnova丨血液总核酸纯化试剂盒预装相关说明书
小程序事件绑定
Leetcode (695) - the largest area of an island
Sort and projection
When steam education enters personalized information technology courses
Prosci LAG-3 recombinant protein specification
Graph embedding learning notes
Welcome to the game and win rich bonuses: Code Golf Challenge officially launched