`
zzu_007
  • 浏览: 23748 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Activity的ViewRoot的创建过程(三)

阅读更多
page7
在这篇文章里, 我们分析一下W类的构造过程. W类是定义在ViewRootImpl类中的一个内部类, W类的定义如下:
    static class W extends IWindow.Stub
    由此可见,  W本质上是一个Binder本地对象, 其实这是会传给WindowManagerService的, WindowManagerService就是通过W来通知Activity对象执行一些操作.

    W的构造函数如下:
    W(ViewRootImpl viewAncestor) {
        mViewAncestor = new WeakReference<ViewRootImpl>(viewAncestor);
        mWindowSession = viewAncestor.mWindowSession;
    }
    由此可见, W拿着ViewRootImpl和WindowSession.
page8
我们分析一下ViewRootImpl的setView函数的实现:
1     public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView) {
2         synchronized (this) {
3             if (mView == null) {
4                 mView = view;
5                 mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
6                 mFallbackEventHandler.setView(view);
7                 mWindowAttributes.copyFrom(attrs);
8                 attrs = mWindowAttributes;
9                 // Keep track of the actual window flags supplied by the client.
10                 mClientWindowLayoutFlags = attrs.flags;
11
12                 setAccessibilityFocus(null, null);
13
14                 if (view instanceof RootViewSurfaceTaker) {
15                     mSurfaceHolderCallback =
16                             ((RootViewSurfaceTaker)view).willYouTakeTheSurface();
17                     if (mSurfaceHolderCallback != null) {
18                         mSurfaceHolder = new TakenSurfaceHolder();
19                         mSurfaceHolder.setFormat(PixelFormat.UNKNOWN);
20                     }
21                 }
22
23                 CompatibilityInfo compatibilityInfo = mCompatibilityInfo.get();
24                 mTranslator = compatibilityInfo.getTranslator();
25
26                 // If the application owns the surface, don't enable hardware acceleration
27                 if (mSurfaceHolder == null) {
28                     enableHardwareAcceleration(mView.getContext(), attrs);
29                 }
30
31                 boolean restore = false;
32                 if (mTranslator != null) {
33                     mSurface.setCompatibilityTranslator(mTranslator);
34                     restore = true;
35                     attrs.backup();
36                     mTranslator.translateWindowLayout(attrs);
37                 }
38                 if (DEBUG_LAYOUT) Log.d(TAG, "WindowLayout in setView:" + attrs);
39
40                 if (!compatibilityInfo.supportsScreen()) {
41                     attrs.flags |= WindowManager.LayoutParams.FLAG_COMPATIBLE_WINDOW;
42                     mLastInCompatMode = true;
43                 }
44
45                 mSoftInputMode = attrs.softInputMode;
46                 mWindowAttributesChanged = true;
47                 mWindowAttributesChangesFlag = WindowManager.LayoutParams.EVERYTHING_CHANGED;
48                 mAttachInfo.mRootView = view;
49                 mAttachInfo.mScalingRequired = mTranslator != null;
50                 mAttachInfo.mApplicationScale =
51                         mTranslator == null ? 1.0f : mTranslator.applicationScale;
52                 if (panelParentView != null) {
53                     mAttachInfo.mPanelParentWindowToken
54                             = panelParentView.getApplicationWindowToken();
55                 }
56                 mAdded = true;
57                 int res; /* = WindowManagerImpl.ADD_OKAY; */
58
59                 // Schedule the first layout -before- adding to the window
60                 // manager, to make sure we do the relayout before receiving
61                 // any other events from the system.
62                 requestLayout();
63                 if ((mWindowAttributes.inputFeatures
64                         & WindowManager.LayoutParams.INPUT_FEATURE_NO_INPUT_CHANNEL) == 0) {
65                     mInputChannel = new InputChannel();
66                 }
67                 try {
68                     mOrigWindowType = mWindowAttributes.type;
69                     mAttachInfo.mRecomputeGlobalAttributes = true;
70                     collectViewAttributes();
71                     res = mWindowSession.addToDisplay(mWindow, mSeq, mWindowAttributes,
72                             getHostVisibility(), mDisplay.getDisplayId(),
73                             mAttachInfo.mContentInsets, mInputChannel);
74                 } catch (RemoteException e) {
75                     mAdded = false;
76                     mView = null;
77                     mAttachInfo.mRootView = null;
78                     mInputChannel = null;
79                     mFallbackEventHandler.setView(null);
80                     unscheduleTraversals();
81                     setAccessibilityFocus(null, null);
82                     throw new RuntimeException("Adding window failed", e);
83                 } finally {
84                     if (restore) {
85                         attrs.restore();
86                     }
87                 }
88                
89                 if (mTranslator != null) {
90                     mTranslator.translateRectInScreenToAppWindow(mAttachInfo.mContentInsets);
91                 }
92                 mPendingContentInsets.set(mAttachInfo.mContentInsets);
93                 mPendingVisibleInsets.set(0, 0, 0, 0);
94                 if (DEBUG_LAYOUT) Log.v(TAG, "Added window " + mWindow);
95                 if (res < WindowManagerGlobal.ADD_OKAY) {
96                     mAttachInfo.mRootView = null;
97                     mAdded = false;
98                     mFallbackEventHandler.setView(null);
99                     unscheduleTraversals();
100                     setAccessibilityFocus(null, null);
101                     switch (res) {
102                         case WindowManagerGlobal.ADD_BAD_APP_TOKEN:
103                         case WindowManagerGlobal.ADD_BAD_SUBWINDOW_TOKEN:
104                             throw new WindowManager.BadTokenException(
105                                 "Unable to add window -- token " + attrs.token
106                                 + " is not valid; is your activity running?");
107                         case WindowManagerGlobal.ADD_NOT_APP_TOKEN:
108                             throw new WindowManager.BadTokenException(
109                                 "Unable to add window -- token " + attrs.token
110                                 + " is not for an application");
111                         case WindowManagerGlobal.ADD_APP_EXITING:
112                             throw new WindowManager.BadTokenException(
113                                 "Unable to add window -- app for token " + attrs.token
114                                 + " is exiting");
115                         case WindowManagerGlobal.ADD_DUPLICATE_ADD:
116                             throw new WindowManager.BadTokenException(
117                                 "Unable to add window -- window " + mWindow
118                                 + " has already been added");
119                         case WindowManagerGlobal.ADD_STARTING_NOT_NEEDED:
120                             // Silently ignore -- we would have just removed it
121                             // right away, anyway.
122                             return;
123                         case WindowManagerGlobal.ADD_MULTIPLE_SINGLETON:
124                             throw new WindowManager.BadTokenException(
125                                 "Unable to add window " + mWindow +
126                                 " -- another window of this type already exists");
127                         case WindowManagerGlobal.ADD_PERMISSION_DENIED:
128                             throw new WindowManager.BadTokenException(
129                                 "Unable to add window " + mWindow +
130                                 " -- permission denied for this window type");
131                         case WindowManagerGlobal.ADD_INVALID_DISPLAY:
132                             throw new WindowManager.InvalidDisplayException(
133                                 "Unable to add window " + mWindow +
134                                 " -- the specified display can not be found");
135                     }
136                     throw new RuntimeException(
137                         "Unable to add window -- unknown error code " + res);
138                 }
139
140                 if (view instanceof RootViewSurfaceTaker) {
141                     mInputQueueCallback =
142                         ((RootViewSurfaceTaker)view).willYouTakeTheInputQueue();
143                 }
144                 if (mInputChannel != null) {
145                     if (mInputQueueCallback != null) {
146                         mInputQueue = new InputQueue(mInputChannel);
147                         mInputQueueCallback.onInputQueueCreated(mInputQueue);
148                     } else {
149                         mInputEventReceiver = new WindowInputEventReceiver(mInputChannel,
150                                 Looper.myLooper());
151                     }
152                 }
153
154                 view.assignParent(this);
155                 mAddedTouchMode = (res & WindowManagerGlobal.ADD_FLAG_IN_TOUCH_MODE) != 0;
156                 mAppVisible = (res & WindowManagerGlobal.ADD_FLAG_APP_VISIBLE) != 0;
157
158                 if (mAccessibilityManager.isEnabled()) {
159                     mAccessibilityInteractionConnectionManager.ensureConnection();
160                 }
161
162                 if (view.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
163                     view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
164                 }
165             }
166         }
167     }
168
第2行(ViewRootImpl->setView)会加锁
第3行(ViewRootImpl->setView)会保证一个ViewRootImpl只对应一个View
第4行(ViewRootImpl->setView)将成员变量mView设置成DecorView

第62行(ViewRootImpl->setView)会调用requestLayout()函数来进行一次layout, 而这是在加入到WindowManagerService管理之前进行的, 关于这部分的分析可以参考View的刷新部分的分析.
第71-73行(ViewRootImpl->setView)会调用WindowSession的addToDisplay函数将mWindow传给WindowManagerService, 关于这部分的分析可以参考Activity和WindowManagerService连接系列的文章.
page9
    我们来看一下PhoneWidnow的getDecorView函数的实现:
    public final View getDecorView() {
        if (mDecor == null) {
            installDecor();
        }
        return mDecor;
    }
    getDecorView函数如果发现mDecor还没有初始化过, 就会调用installDecor函数来构造一个DecorView
分享到:
评论

相关推荐

    联想 viewroot简介

    1. **启动过程**:在Activity启动的过程中,ActivityThread的handler函数会处理LAUNCH_ACTIVITY消息,此过程中会调用ViewRoot的setView()方法。 2. **绘制请求**:requestLayout()实际上向消息队列发送了一个请求GUI...

    Activity启动流程进程启动

    创建完后,Activity 需要把创建好的界面显示到屏幕上,调用的流程为:WindowManager 类 ——&gt; ViewRoot 类 ——&gt; WMS 远程接口,这样就完成一个窗口添加到屏幕上。 知识点总结 * ActivityThread 是 Android 应用...

    android获取根View的方法

    在Kotlin中,我们可以创建一个扩展函数来简化获取根View的过程: ```kotlin fun AppCompatActivity.getRootView(): View { return findViewById(android.R.id.content) } ``` 然后在任何Activity中,只需调用`...

    Android Graphics Architecture.pdf

    3. **创建Surface**: ViewRoot通过调用`WindowManagerService.addWindow()`来为新窗口创建一个Surface,并将Surface传递给Activity。 4. **绘制视图层次结构**: Activity通过`ViewRoot.setView()`方法设置其视图层次...

    Android自定义组件解析[郝留有]

    在Activity的创建过程中,通过setContentView()方法设置用户界面,将各种View(视图)组件添加至PhoneWindow的ContentParent中。 随着Activity线程的继续执行,到达makeVisible()时,根View(即DecoView)将被加入...

    android record view,无需root权限

    然而,早期的Android版本并不直接支持这一功能,开发者需要借助第三方库或者root权限来实现。随着Android系统的发展,现在可以实现无需root权限的屏幕录制。本文将深入探讨如何在Android应用中实现这一功能,主要...

    Android中View绘制流程详细介绍

    接着,Activity的根View会被添加到WindowManager中,此时,`WindowManagerImpl`会创建一个`ViewRoot`来管理这个根View。 **DecorView的创建** DecorView是Window的最顶层View,它是`PhoneWindow`的内部类,继承自`...

    Android开发艺术探索.任玉刚(带详细书签).pdf

    4.1 初识ViewRoot和DecorView 174 4.2 理解MeasureSpec 177 4.2.1 MeasureSpec 177 4.2.2 MeasureSpec和LayoutParams的对应关系 178 4.3 View的工作流程 183 4.3.1 measure过程 183 4.3.2 layout过程 193 ...

    Android_Surface系统的实现

    该对象会创建一个ViewRoot实例来处理与WMS之间的交互。 - **IWindowSession 和 IWindow 接口:**这些是标准的AIDL接口,用于ViewRoot与WMS之间的通信。IWindowSession用于跨进程通信,而IWindow则被WMS用于调用View...

    Android开发艺术探索1

    - **Window创建过程**:了解Activity、Dialog、Toast创建Window的过程。 9. **四大组件的工作过程** - **Activity和服务**:理解它们的启动、停止、绑定等生命周期过程。 - **BroadcastReceiver**:广播接收器的...

    Android开发艺术探索

     4.1 初识ViewRoot和DecorView / 174  4.2 理解MeasureSpec / 177  4.2.1 MeasureSpec / 177  4.2.2 MeasureSpec和LayoutParams的对应关系 / 178  4.3 View的工作流程 / 183  4.3.1 measure过程 / 183  4.3.2...

    android开发艺术探索高清完整版PDF

    / 301 8.2.3 Window的更新过程 / 303 8.3 Window的创建过程 / 304 8.3.1 Activity的Window创建过程 / 304 8.3.2 Dialog的Window创建过程 / 308 8.3.3 Toast的Window创建过程 / 311 第9章 四大组件的工作过程 ...

    view面试专题.docx

    2. **View与ViewRoot的关联** - 在`handleResumeActivity`时,`Activity`的`onResume`方法被调用。 - `WindowManager`将`DecorView`设置给`ViewRootImpl`。 - 此时`DecorView`加载到了`Window`中。 3. **View的...

    android 7.0非root下 实现静默安装 多种方式

    可以创建一个Intent,指定ACTION_VIEW并附加一个指向APK文件的URI。然后,使用FLAG_ACTIVITY_NEW_TASK和FLAG_GRANT_READ_URI_PERMISSION标志启动这个Intent,这样在某些情况下可以触发静默安装。但是,这种方法的...

    Android代码实现截屏

    2. **创建Bitmap**: 创建一个与root view相同大小的`Bitmap`对象。可以使用`Bitmap.createBitmap()`方法,传入view的宽度、高度和颜色格式。 3. **准备Canvas**: 创建一个`Canvas`对象,将刚才创建的`Bitmap`作为...

    android事件的处理模型和多线程的处理方法

    这个过程通常发生在ActivityThread的handleResumeActivity函数中,通过创建ViewRoot实例并调用setView方法。在这个过程中,Activity注册了InputChannel,使得InputManager可以将键盘事件分发给正确的Activity。注册...

    Android核心剖析之Framework概述

    ViewRoot继承自Handler,作为WmS与客户端间通信的枢纽,负责接收来自WmS的指令,执行相应的窗口操作。W类作为Binder的子类,用于实现跨进程通信,确保服务端与客户端之间的数据交换。 **5. WindowManager类** ...

    Android例子源码免root实现截屏.zip

    3. **绘制屏幕到位图**:使用`View.draw()`方法,将根视图的内容绘制到之前创建的位图上。这一步完成了实际的截图过程。 4. **保存截图**:截图完成后,使用`Bitmap.compress()`方法,将位图保存为PNG或JPEG文件。...

Global site tag (gtag.js) - Google Analytics