安卓Android

Android绘制源码分析(上)

2019-11-01  本文已影响0人  大佬的上半生
Android屏幕的框架
image.png
Activity与PhoneWindow与DecorView关系
image.png

Window

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.png
ViewRootImpl

实现了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需要管理所有的窗口。

Android绘制源码分析(中)

上一篇下一篇

猜你喜欢

热点阅读