Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2019-03-26: Window和DecorView是什么?DecorView又是如何和Window建立联系的? #13

Open
FeatherHunter opened this issue Mar 25, 2019 · 9 comments

Comments

@FeatherHunter
Copy link
Collaborator

No description provided.

@Moosphan Moosphan added this to In progress in Track | ToDo | 建议收集 Mar 26, 2019
@Moosphan Moosphan added the underway the daily question is solving now label Mar 26, 2019
@Ssuiyingsen
Copy link

emmmm.............看到这个问题 我怂了 告辞 接下来有请老苏进行回答。

@manondidi
Copy link

manondidi commented Mar 26, 2019

一个activity 有一个window,
一个window 有一个DecorView
setcontent(R.layout.xxx) 就是在decorview中
decorview只有一个子元素linearlayout
decorview是一个页面的顶层view,
之前做播放器,在全屏的时候,把播放器从原来页面上的parent中remove出来
再add到decorview中.
就知道这么多了...

@Moosphan
Copy link
Owner

Moosphan commented Mar 26, 2019

WindowWindowManager 最顶层的视图,它负责背景(窗口背景)、Title之类的标准的UI元素,Window 是一个抽象类,整个Android系统中, PhoneWindowWindow 的唯一实现类。至于 DecorView,它是一个顶级 View,内部会包含一个竖直方向的LinearLayout,这个 LinearLayout 有上下两部分,分为 titlebar 和 contentParent 两个子元素,contentParent 的 id 是 content,而我们自定义的 Activity 的布局就是 contentParent 里面的一个子元素。View 层的所有事件都要先经过 DecorView 后才传递给我们的 ViewDecorViewWindow 的一个变量,即 DecorView 作为一切视图的根布局,被 Window 所持有,我们自定义的 View 会被添加到 DecorView ,而DecorView 又会被添加到 Window 中加载和渲染显示。此处放一张它们的简单内部层次结构图:

3C20E3A3969706AE73B69B4841FC42AF

@FeatherHunter
Copy link
Collaborator Author

DecorView的作用

  1. DecorView是顶级View,本质就是一个FrameLayout
  2. 包含了两个部分,标题栏和内容栏
  3. 内容栏id是content,也就是activity中setContentView所设置的部分,最终将布局添加到id为content的FrameLayout中
  4. 获取content:ViewGroup content = findViewById(R.android.id.content)
  5. 获取设置的View:content.getChidlAt(0)

Window是什么?

  1. 表示一个窗口的概念,是所有View的直接管理者,任何视图都通过Window呈现(单击事件由Window->DecorView->View; Activity的setContentView底层通过Window完成)
  2. Window是一个抽象类,具体实现是PhoneWindow
  3. 创建Window需要通过WindowManager创建
  4. WindowManager是外界访问Window的入口
  5. Window具体实现位于WindowManagerService
  6. WindowManagerWindowManagerService的交互是通过IPC完成

DecorView又是如何和Window建立联系的?

  1. 在Activity的启动流程中,处理onResume()的相关方法中,将DecorView作为Window的成员变量保存到Window内部
  2. DecorView与Window建立联系又有什么用呢?例如Activity的onSaveInstanceState()进行数据保存时,就通过window内部的DecorView触发整个View树进行状态保存
//ActivityThread.java
final void handleResumeActivity(IBinder token, ...) {
  //1. 创建DecorView,设置为不可见INVISIBLE
  View decor = r.window.getDecorView();
  decor.setVisibility(View.INVISIBLE);
  //2. 获取到WindowManager, addView方法将DecorView添加到Window中
  ViewManager wm = a.getWindowManager();
  wm.addView(decor, l);
  //3. 将DecorView设置为visible
  r.activity.makeVisible();
}

@shortybin
Copy link

shortybin commented Mar 28, 2019

DecorView的作用

  1. DecorView是顶级View,本质就是一个FrameLayout
  2. 包含了两个部分,标题栏和内容栏
  3. 内容栏id是content,也就是activity中setContentView所设置的部分,最终将布局添加到id为content的FrameLayout中
  4. 获取content:ViewGroup content = findViewById(R.android.id.content)
  5. 获取设置的View:content.getChidlAt(0)

Window是什么?

  1. 表示一个窗口的概念,是所有View的直接管理者,任何视图都通过Window呈现(单击事件由Window->DecorView->View; Activity的setContentView底层通过Window完成)
  2. Window是一个抽象类,具体实现是PhoneWindow
  3. 创建Window需要通过WindowManager创建
  4. WindowManager是外界访问Window的入口
  5. Window具体实现位于WindowManagerService
  6. WindowManagerWindowManagerService的交互是通过IPC完成

DecorView又是如何和Window建立联系的?

  1. 在Activity的启动流程中,处理onResume()的相关方法中,将DecorView作为Window的成员变量保存到Window内部
  2. DecorView与Window建立联系又有什么用呢?例如Activity的onSaveInstanceState()进行数据保存时,就通过window内部的DecorView触发整个View树进行状态保存
//ActivityThread.java
final void handleResumeActivity(IBinder token, ...) {
  //1. 创建DecorView,设置为不可见INVISIBLE
  View decor = r.window.getDecorView();
  decor.setVisibility(View.INVISIBLE);
  //2. 获取到WindowManager, addView方法将DecorView添加到Window中
  ViewManager wm = a.getWindowManager();
  wm.addView(decor, l);
  //3. 将DecorView设置为visible
  r.activity.makeVisible();
}

关于 Windows 是什么,第三个有些问题,Windows 的创建是在 Activity 的 attach 方法中创建的,直接 new 了个 PhoneWindows 对象,而 WindowsManager 的创建是在 Activity 的 attach 方法中,创建完 Windows 后,通过 Windows 的 setWindowManager 方法创建的 WindowsManager,我觉得 WindowsManager 的创建是通过 Windows 去创建的。

具体的 Windows 是怎么创建的 WindowsManager ? 它是在 ContextImpl 中通过 SystemServiceRegistry.getSystemService(this, name); 中通过服务名称获取的 WindowsManager,WindowsManager 是放在一个 HashMap 当中的,是在 SystemServiceRegistry 初始化的时候已经创建好了 WindowManagerImpl

final void attach(){
    ......
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    ......
    mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    ......
}

我看到的代码是这样的,不清楚我们描述的是不是同一个问题

@Alex-Cin
Copy link

事实上, 牵涉两个方法, attach 和 onResume, 一个是创建视图, 创建 PhoneWindow对象, resume时把decorView添加到WindowManager上; 还有再补充回答 Choreographer vSync SurfaceFlinger 等等;
面试过程, 不可能全都背下来, 记得一下关键点, 等待面试官提醒;

@Moosphan Moosphan added View相关 and removed underway the daily question is solving now labels Apr 11, 2019
@fewwind
Copy link

fewwind commented May 28, 2019

DecorView的作用

  1. DecorView是顶级View,本质就是一个FrameLayout
  2. 包含了两个部分,标题栏和内容栏
  3. 内容栏id是content,也就是activity中setContentView所设置的部分,最终将布局添加到id为content的FrameLayout中
  4. 获取content:ViewGroup content = findViewById(R.android.id.content)
  5. 获取设置的View:content.getChidlAt(0)

Window是什么?

  1. 表示一个窗口的概念,是所有View的直接管理者,任何视图都通过Window呈现(单击事件由Window->DecorView->View; Activity的setContentView底层通过Window完成)
  2. Window是一个抽象类,具体实现是PhoneWindow
  3. 创建Window需要通过WindowManager创建
  4. WindowManager是外界访问Window的入口
  5. Window具体实现位于WindowManagerService
  6. WindowManagerWindowManagerService的交互是通过IPC完成

DecorView又是如何和Window建立联系的?

  1. 在Activity的启动流程中,处理onResume()的相关方法中,将DecorView作为Window的成员变量保存到Window内部
  2. DecorView与Window建立联系又有什么用呢?例如Activity的onSaveInstanceState()进行数据保存时,就通过window内部的DecorView触发整个View树进行状态保存
//ActivityThread.java
final void handleResumeActivity(IBinder token, ...) {
  //1. 创建DecorView,设置为不可见INVISIBLE
  View decor = r.window.getDecorView();
  decor.setVisibility(View.INVISIBLE);
  //2. 获取到WindowManager, addView方法将DecorView添加到Window中
  ViewManager wm = a.getWindowManager();
  wm.addView(decor, l);
  //3. 将DecorView设置为visible
  r.activity.makeVisible();
}

关于 Windows 是什么,第三个有些问题,Windows 的创建是在 Activity 的 attach 方法中创建的,直接 new 了个 PhoneWindows 对象,而 WindowsManager 的创建是在 Activity 的 attach 方法中,创建完 Windows 后,通过 Windows 的 setWindowManager 方法创建的 WindowsManager,我觉得 WindowsManager 的创建是通过 Windows 去创建的。

具体的 Windows 是怎么创建的 WindowsManager ? 它是在 ContextImpl 中通过 SystemServiceRegistry.getSystemService(this, name); 中通过服务名称获取的 WindowsManager,WindowsManager 是放在一个 HashMap 当中的,是在 SystemServiceRegistry 初始化的时候已经创建好了 WindowManagerImpl

final void attach(){
    ......
    mWindow = new PhoneWindow(this, window, activityConfigCallback);
    ......
    mWindow.setWindowManager(
                (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
                mToken, mComponent.flattenToString(),
                (info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
    ......
}

我看到的代码是这样的,不清楚我们描述的是不是同一个问题

WindowManager的操作是有其实现类WindowManagerImpl的内部类WindowManagerGlobal来完成的

@maoruibin
Copy link

以下是 Window 中的 View 关系

一个 Activity 对应一个 Window 对象,Window 是一个抽象类,它唯一的实现是 PhoneWindow。

一个 Window 持有一个 DecorView。

Activity 中几乎所有的 View 相关逻辑都在 DecorView 中控制。

Activity 的启动通过 ActivityManagerService 完成,具体在 ActivityThread 的 performLaunchActivity 完成,Activity 的启动、暂停、销毁等操作都在 ActivityThread 完成,而消息的分发则通过 ActivityThread 中的 Handler 实例 mH 完成。

在上述方法中执行 Activity 启动的时候,先是用类加载的方法根据 Activity 类名创建了 Activity 对象,

ActivityThread#performLaunchActivity

private void performLaunchActivity(){
      Activity activity = null;
    java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
    //初始化 Activity 
    activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);

    if (activity != null) {
      Context appContext = createBaseContextForActivity(r, activity);
      CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
      Configuration config = new Configuration(mCompatConfiguration);
      // 执行 attach 
      activity.attach(appContext, this, getInstrumentation(), r.token,
              r.ident, app, r.intent, r.activityInfo, title, r.parent,
                        r.embeddedID, r.lastNonConfigurationInstances, config,
                        r.voiceInteractor);
    }
}

接着会调用 activity 的 attach 方法。

在 attach 方法中会进行 mWindow 的实例化

final void attach(Context context, ActivityThread aThread,
            Instrumentation instr, IBinder token, int ident,
            Application application, Intent intent, ActivityInfo info,
            CharSequence title, Activity parent, String id,
            NonConfigurationInstances lastNonConfigurationInstances,
            Configuration config, String referrer, IVoiceInteractor voiceInteractor,
            Window window) {
      ...
        //实例化 window 对象  
        mWindow = new PhoneWindow(this, window);
        mWindow.setWindowControllerCallback(this);
        mWindow.setCallback(this);
        mWindow.setOnWindowDismissedCallback(this);
    ...
 }

这样 PhoneWindow 就跟 Activity 关联了起来,每一个 PhoneWindow 都持有一个 DecorView 对象

public class PhoneWindow extends Window{
  // This is the top-level view of the window, containing the   window decor.
  private DecorView mDecor; 
}

DecorView 是在什么地方实例化的呢,在 PhoneWindow 的构造方法中可以看到

    /**
     * Constructor for main window of an activity.
     */
    public PhoneWindow(Context context, Window preservedWindow,
            ActivityConfigCallback activityConfigCallback) {
        this(context);
        if (preservedWindow != null) {
            mDecor = (DecorView) preservedWindow.getDecorView();
            mElevation = preservedWindow.getElevation();
        }
        ...
    }

这里通过 window 的 getDecorView() 方法获取,在 getDecorView 方法中很快就可以发现一个很重要的方法

installDecor()

这个方法会去实例化 DecorView,并进行一系列的操作,比如 title 的初始化等等...

这样 activity 启动后,整个 Window DecorView 相关的 View 都初始化完毕。

开发者在 activity 的 onCreate 时机调用 setContent 方法,将指定的布局、View 传递给 activity,activity 最终把这个 view 通过 window 传递给 DecorView,然后被 add 到 DecorView 的 content 布局中。

@mlinqirong
Copy link

mlinqirong commented Dec 16, 2021

activity是一个载体 里面有phoneWindow承继于window window是Activity的一个窗体 DevorView是window中的最顶层view DevorView的孩子有个LinearLayout 包含状态栏和我们setContentView的布局
Activity->window->DevorView->View

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Development

No branches or pull requests

9 participants