当前位置:网站首页>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
边栏推荐
- The development of research tourism practical education helps the development of cultural tourism industry
- Monorepo管理方法论和依赖安全
- Hongmeng OS' fourth learning
- Schema and model
- Sort and projection
- Abnova丨 MaxPab 小鼠源多克隆抗体解决方案
- Is it safe to open a stock account by mobile phone? My home is relatively remote. Is there a better way to open an account?
- 资源道具化
- Model method
- Abnova丨CRISPR SpCas9 多克隆抗体方案
猜你喜欢
Classic implementation of the basic method of intelligent home of Internet of things
Cutting edge technology for cultivating robot education creativity
Abnova丨血液总核酸纯化试剂盒预装相关说明书
Return to blowing marshland -- travel notes of zhailidong, founder of duanzhitang
Which is the best online collaboration product? Microsoft loop, notion, flowus
教你自己训练的pytorch模型转caffe(三)
Graph embedding learning notes
14、Transformer--VIT TNT BETR
Applet event binding
Research and development efficiency improvement practice of large insurance groups with 10000 + code base and 3000 + R & D personnel
随机推荐
Abnova e (diii) (WNV) recombinant protein Chinese and English instructions
插值查找的简单理解
Point cloud file Dat file read save
The development of research tourism practical education helps the development of cultural tourism industry
基于AVFoundation实现视频录制的两种方式
Cutting edge technology for cultivating robot education creativity
Applet project structure
Duchefa丨D5124 MD5A 培养基中英文说明书
Clear app data and get Icon
How to make ERP inventory accounts of chemical enterprises more accurate
1、强化学习基础知识点
Abnova丨 MaxPab 小鼠源多克隆抗体解决方案
Make Jar, Not War
10000+ 代码库、3000+ 研发人员大型保险集团的研发效能提升实践
研學旅遊實踐教育的開展助力文旅產業發展
【愚公系列】2022年7月 Go教学课程 004-Go代码注释
Informatics Olympiad 1340: [example 3-5] extended binary tree
How to renew NPDP? Here comes the operation guide!
Abnova 环孢素A单克隆抗体,及其研究工具
Nprogress plug-in progress bar