Java-WIndow和Activity和View
ActivityThread handleLaunchActivity() performLaunchActivity()--->activity.attach()
1: 创建PhoneWindow 将xml加载到PhoneWindow的DecorView上
attach(){
//创建 PhoneWindow
mWindow = new PhoneWindow(this, window, activityConfigCallback);
}
Activity -->setContentView(){
(PhoneWindow)getWindow().setContentView(layoutResID);
}
创建PhoneWindow 创建DecorView 将xml加载到DecorView中
PhoneWindow-->{
setContentView(){
//创建 DecorView
installDecor(){
//创建 DecorView
mDecor = generateDecor(-1);
//获取父类根布局
mContentParent = generateLayout(mDecor){
//加载 res传递过来的xml
mDecor.onResourcesLoaded(mLayoutInflater, layoutResource);
};
};
}
}
2:处理展示---> window.addView
ActivityThread--->handleResumeActivity(){
//执行Activity onResume
重点:
执行Activity onResume的时候 View还没加载到 Window上所以此时还获取不了控件宽高
if (!performResumeActivity(r, finalStateRequest, reason)){};
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
//WindowManager WindowManagerImpl是WindowManager的实现类实质是到WindowManagerImpl
WindowManagerImpl
此对象实现了{@link ViewManager}接口,
允许您将任何View子类添加为屏幕上的顶级窗口。
定义了其他窗口管理器特定的布局参数,用于控制窗口的显示方式。
它还实现了{@link WindowManager}接口,允许您控制连接到设备的显示。
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
//将decorview 加载的View 添加到屏幕上
(WindowManagerImpl)wm.addView(decor, l);
]
WindowManagerImpl
此对象实现了{@link ViewManager}接口,
允许您将任何View子类添加为屏幕上的顶级窗口。
定义了其他窗口管理器特定的布局参数,用于控制窗口的显示方式。
它还实现了{@link WindowManager}接口,允许您控制连接到设备的显示。
WindowManagerImpl -->{
@Override
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
//view 是decorview 以及布局对象 mContext.getDisplay()是获取了一个屏幕对象
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
}
为与任何特定上下文无关的操作提供与系统窗口管理器的低级通信
WindowManagerGlobal-->{
addView(){
root = new ViewRootImpl(view.getContext(), display);
root.setView(view, wparams, panelParentView);
}
}
视图层次结构的顶部,实现视图和WindowManager之间所需的协议
ViewRootImpl{
//保证了绘制同步
synchronized (this) {
requestLayout();
requestLayout 是刷新布局的操作,
调用此方法后 ViewRootImpl 所关联的 View 也执行 measure -> layout -> draw 操作,
确保在 View 被添加到 Window 上显示到屏幕之前,已经完成测量和绘制操作。
// 将 window的内容显示到屏幕上
res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), mWinFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mOutsets, mAttachInfo.mDisplayCutout, mInputChannel);
}
}
mWindowSession{
mWindowSession = WindowManagerGlobal.getWindowSession();
public static IWindowSession getWindowSession() {
synchronized (WindowManagerGlobal.class) {
if (sWindowSession == null) {
try {
InputMethodManager imm = InputMethodManager.getInstance();
// windowManager 就是一个WindowManagerService
IWindowManager windowManager = getWindowManagerService();
sWindowSession = windowManager.openSession(
new IWindowSessionCallback.Stub() {
@Override
public void onAnimatorScaleChanged(float scale) {
ValueAnimator.setDurationScale(scale);
}
},
imm.getClient(), imm.getInputContext());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
return sWindowSession;
}
}
}
WindowManagerService --->{
openSession(){
if (client == null) throw new IllegalArgumentException("null client");
if (inputContext == null) throw new IllegalArgumentException("null inputContext");
this 代表 WindowManagerService
Session session = new Session(this, callback, client, inputContext);
return session;
}
}
mWindowSession.addToDisplay(){
@Override
public int addToDisplay(IWindow window, int seq, WindowManager.LayoutParams attrs,
int viewVisibility, int displayId, Rect outFrame, Rect outContentInsets,
Rect outStableInsets, Rect outOutsets,
DisplayCutout.ParcelableWrapper outDisplayCutout, InputChannel outInputChannel) {
return mService.addWindow(this, window, seq, attrs, viewVisibility, displayId, outFrame,
outContentInsets, outStableInsets, outOutsets, outDisplayCutout, outInputChannel);
}
}
又回到了WindowManagerService addWindow{
final WindowState win = new WindowState(this, session, client, token, parentWindow,
appOp[0], seq, attrs, viewVisibility, session.mUid,
session.mCanAddInternalSystemWindow);
win.attach();
}
为什么win.attach()是创建与SurfaceFlinger通信的?简单了解下。
跟踪下去是创建了SurfaceSession对象,这个创建进入native,最终创建了一个与SurfaceFlinger通信的 SurfaceComposerClient。 因此,可以与SurfaceFlinger进行通信。
ViewRootImpl创建时 就创建的mSurface,mSurface是ViewRootImpl的成员变量,此时创建的Surface什么都没有,最后通过relayoutWindow()进入WMS 一步步向SurfaceFlinger发出请求。
这时几处相关代码。
WindowState{
void attach() {
if (localLOGV) Slog.v(TAG, "Attaching " + this + " token=" + mToken);
mSession.windowAddedLocked(mAttrs.packageName);
}
}
Session{
void windowAddedLocked(String packageName) {
mPackageName = packageName;
mRelayoutTag = "relayoutWindow: " + mPackageName;
if (mSurfaceSession == null) {
if (WindowManagerService.localLOGV) Slog.v(
TAG_WM, "First window added to " + this + ", creating SurfaceSession");
mSurfaceSession = new SurfaceSession();
if (SHOW_TRANSACTIONS) Slog.i(
TAG_WM, " NEW SURFACE SESSION " + mSurfaceSession);
mService.mSessions.add(this);
if (mLastReportedAnimatorScale != mService.getCurrentAnimatorScale()) {
mService.dispatchNewAnimatorScaleLocked(this);
}
}
mNumWindow++;
}
}
窗口管理核心类:DisplayContent,WindowToken和WindowState
DisplayContent 理解为显示器 管理一个显示器上的各个窗口
WindowState 窗口状态可以理解为一个窗口(各种状态)
WindowToken 可以理解未WindowState 的集合
WindowManager 窗口管理
WindowMaangerService 窗口管理
WindowManagerService 负责窗口(window)管理,窗口动画,输入法,Surface 管理
-窗口管理: 负责窗口的启动,添加和删除,另外窗口的大小也时有 WMS 管理的,
管理窗口的核心成员有DisplayContent,WindowToken 和 WindowState
-窗口动画:窗口间进行切换时,使用窗口动画可以更好看一些,窗口动画由
WMS 动画子系统来负责,动画的管理系统为 WindowAnimator
-输入系统的中转站:通过对窗口触摸而产生的触摸事件,InputManagerServer(IMS) 会对触摸事件进行处理,他会寻找一个最合适的窗口来处理触摸反馈信息,
WMS 是窗口的管理者,因此理所当然的就成为了输入系统的中转站
-Surface管理:
窗口并不具备绘制的功能,因此每个窗口都需要有一个块 Surface 来供自己绘制,为每个窗口分配 Surface 是由 WMS 来完成的。