Android绘制源码分析(上)
Android屏幕的框架
image.pngActivity与PhoneWindow与DecorView关系
image.pngWindow
1.Windows是一个接口,实现它的是PhoneWindow
2.WindowManager创建一个window,WindowManager 为每一个window创建一个surface,并把该surface传递给应用以便应用在上面绘制,一个应用有很多Window。
3.Window是屏幕上用于绘制各种UI元素(比如Button,TextView)及响应用户输入事件(键盘事件)的一个矩形区域,它独立绘制,不与其他界面产生影。
4.在Android系统中,每个Window是独占一个Surface实例的显示区域,每个窗口的Surface由WindowManagerService分配。
每个Window都对应着一个View和一个ViewRootImpl,Window和View通过ViewRootImpl来建立联系,对于Activity来说,ViewRootImpl是连接WindowManager和DecorView的纽带,绘制的入口是由ViewRootImpl的performTraversals方法来发起Measure,Layout,Draw等流程的
5.Window 是 Android 中窗口的宏观定义,主要是管理 View 的创建,以及与 ViewRootImpl 的交互,将 Activity 与 View 解耦
DecorView
这个是根布局,包含了ActionBar,它就是我们看到的标题栏,另一个是ContentView(窗口内容的容器),DecorView继承了FragmentLayout,Activity生命周期的起点——onCreate回调方法里使用setContentView就是成了它的子View。每个Activity都与一个PhoneWindow相关联,用户界面则由PhoneWindow所承载,
ActionBar
image.png另一个是ContentView
image.pngViewRootImpl
实现了ViewParent,对View的整个具体操作流程,是连接WindowManager和DecorView的纽带
1.构造方法
public ViewRootImpl(Context context, Display display) {
String processorOverrideName = context.getResources().getString(
R.string.config_inputEventCompatProcessorOverrideClassName);
if (processorOverrideName.isEmpty()) {
// No compatibility processor override, using default.
mInputCompatProcessor = new InputEventCompatProcessor(context);
} else {
InputEventCompatProcessor compatProcessor = null;
try {
final Class<? extends InputEventCompatProcessor> klass =
(Class<? extends InputEventCompatProcessor>) Class.forName(
processorOverrideName);
compatProcessor = klass.getConstructor(Context.class).newInstance(context);
} catch (Exception e) {
Log.e(TAG, "Unable to create the InputEventCompatProcessor. ", e);
} finally {
mInputCompatProcessor = compatProcessor;
}
}
if (!sCompatibilityDone) {
sAlwaysAssignFocus = mTargetSdkVersion < Build.VERSION_CODES.P;
sCompatibilityDone = true;
}
loadSystemProperties();
}
2.在WindowManagerGlobal中实例化
public void addView(View view, ViewGroup.LayoutParams params,
Display display, Window parentWindow) {
if (view == null) {
throw new IllegalArgumentException("view must not be null");
}
final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams) params;
ViewRootImpl root;
View panelParentView = null;
root = new ViewRootImpl(view.getContext(), display);
view.setLayoutParams(wparams);
mViews.add(view);
mRoots.add(root);
mParams.add(wparams);
// do this last because it fires off messages to start doing things
try {
root.setView(view, wparams, panelParentView);
} catch (RuntimeException e) {
// BadTokenException or InvalidDisplayException, clean up.
if (index >= 0) {
removeViewLocked(index, true);
}
throw e;
}
}
}
3.WindowManagerImpl中调用了addView
private final WindowManagerGlobal mGlobal = WindowManagerGlobal.getInstance();
public void addView(@NonNull View view, @NonNull ViewGroup.LayoutParams params) {
applyDefaultToken(params);
mGlobal.addView(view, params, mContext.getDisplay(), mParentWindow);
}
4.PhoneWindow的setContentView()调用了步骤3
public void setContentView(View view, ViewGroup.LayoutParams params) {
// Note: FEATURE_CONTENT_TRANSITIONS may be set in the process of installing the window
// decor, when theme attributes and the like are crystalized. Do not check the feature
// before this happens.
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
view.setLayoutParams(params);
final Scene newScene = new Scene(mContentParent, view);
transitionTo(newScene);
} else {
mContentParent.addView(view, params);
}
mContentParent.requestApplyInsets();
final Callback cb = getCallback();
if (cb != null && !isDestroyed()) {
cb.onContentChanged();
}
mContentParentExplicitlySet = true;
}
5.Activity的setContext()就是这个
public void setContentView(View view) {
getWindow().setContentView(view);
initWindowDecorActionBar();
}
总结1:由上面分析是连接WindowManager和DecorView的纽带,Activity中的setContentView就是成了DecorView它的子View
6.WindowManagerImpl addView同时也在ScrollView调用
@Override
public void addView(View child) {
if (getChildCount() > 0) {
throw new IllegalStateException("ScrollView can host only one direct child");
}
super.addView(child);
}
总结2:ViewRootImpl管理DecorView的子类增改删
WindowManager窗口管理
管理窗口的一些状态属性(view 的增加,删除,窗口位置,更新等等),它管理window和WindowManagerService交互,由ViewRoot完成。主要的方法有:addview(),updateViewLayout();removeView()。
WindowManager是一个接口,WindowManagerImpl 是它的实现类。
WindowManager 里面维护了三个变量:mViews(根view),mRoots(viewroot),mParams(一些相关变量),由 WindowManagerGlobal 维护它们。
WindowManagerService
对系统中的所有窗口进行管理,它和WindowManager区别是WindowManager管理的是单独的窗口,而WindowManagerService需要管理所有的窗口。