美文网首页
Window相关(艺术探索读书笔记)

Window相关(艺术探索读书笔记)

作者: 最美下雨天 | 来源:发表于2019-07-05 20:05 被阅读0次

Window是一个抽象类,具体实现是PhoneWindow,如果我们要创建一个Window必须要通过Window的管理类(WindowManager)来完成,而Window的具体的实现是在WindowManagerService中

也就是说创建Window的过程就是WindowManager和WindowManagerService通过IPC交互的一个过程

相关类作用以及之间的关联

ViewRootImpl、DecorView、Window、WindowManager、WindowManagerService、WindowManagerGlobal

DecorView:系统根据不同的theme会选择性的加载一个布局文件(decor.addView()这种方式,新版本在onResourcesLoaded这个方法中),比如这个:
screen_custom_title.xml

<?xml version="1.0" encoding="utf-8"?>
<!--
This is a custom layout for a screen.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:fitsSystemWindows="true">
    <!-- Popout bar for action modes -->
    <ViewStub android:id="@+id/action_mode_bar_stub"
              android:inflatedId="@+id/action_mode_bar"
              android:layout="@layout/action_mode_bar"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:theme="?attr/actionBarTheme" />
    <FrameLayout android:id="@android:id/title_container" 
        android:layout_width="match_parent" 
        android:layout_height="?android:attr/windowTitleSize"
        android:transitionName="android:title"
        style="?android:attr/windowTitleBackgroundStyle">
    </FrameLayout>
    <FrameLayout android:id="@android:id/content"
        android:layout_width="match_parent" 
        android:layout_height="0dip"
        android:layout_weight="1"
        android:foregroundGravity="fill_horizontal|top"
        android:foreground="?android:attr/windowContentOverlay" />
</LinearLayout>

我们通过setContentView方法设置的布局文件就是作为这个id为content的子元素的

第二次编辑(北邮)

  • WindowManager是外界访问Window的入口,Window的具体实现位于WindowManagerService中,WindowManager和WindowManagerService的交互是通过IPC来完成的
  • WindowManager中有个内部类LayoutParams,LayoutParams中有两个属性flags、type
  • flags控制的是Window的显示特性,比如说能不能获取焦点,能不能点击,常见的:

FLAG_NOT_FOCUSABLE 不需要获取焦点,也不需要接收各种输入事件,此标记会同时启用FLAG_NOT_TOUCH_MODAL,最终事件会直接传递给下层具有焦点的Window

FLAG_NOT_TOUCH_MODAL 系统会将当前Window区域以外的单击事件传递给下面的Window,当前Window区域以内的单击事件则自己处理

FLAG_NOT_TOUCH_MODAL 可以让Window显示在锁屏的界面上

  • type表示的是同的类型:应用Window、子Window、系统Window,子Window不能单独存在,需要附属在特定的Window之中
    应用Window的层级:1到99
    子Window的层级:1000到1999
    系统Window的层级:2000到2999
    层级大的会覆盖在层级小的Window上面

如果要创建系统Window,需要声明权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
一般可以使用:TYPE_SYSTEM_OVERLAY或者TYPE_SYSTEM_ERROR

  • Window 是一个比较抽象的概念,它具体的表现形式就是它里面的View,操作Window其实就是改变它内部的View,View才是Window存在的实体

  • WindowManager是一个抽象类,具体的实现类是WindowManagerImpl,而在WindowManagerImpl中对view的具体操作是通过WindowManagerGlobal实现的

  • 根据官方文档,ViewRootImpl是WindowManager和View通信的桥梁,实现了它们之间通信所需的协议

  • WindowManager对View的添加:首先是调用WindowManagerImpl的addView方法,在WindowManagerImpl的addView方法中会调用WindowManagerG咯阿布了的addView方法,在WindowManagerGloable的addView方法中new了一个ViewRootImpl,所以我认为addView方法调用了几次,这个Window就有几个ViewRootImpl,最终会调用ViewRoot的setView方法,setView方法中会执行requestLayout并将具体的添加工作交给WindowManagerService进行(Binder机制,IPC调用)

  • WindowManager对View的删除:简单来说也是通过ViewRootImpl来实现的,最终在ViewRootImpl中会通过IPC让WindowManagerService来实现具体的删除操作

Activity与Window

问题:

1、Activity与Window有什么关系,在Activity初始化的过程中Window是什么时候被创建的?
2、Activity的setContentView(View view)方法,最终是将view设置给了谁,这个view是如何被添加到Window中的,是什么时候添加的?

  • Activity的初始化时在ActivityThread的performLaunchActivity()方法完成的,首先会new出一个Activity实例,接着调用Activity的attach()方法,在attach方法内部会new出一个PhoneWindow对象
  • Activity的setContentView方法内部是调用的Window的setContentView方法,也就是PhoneWindow的setContentView方法,在PhoneWindow对象的setContentView方法内部首先会new一个DecorView对象(DecorView是一个FrameLayout),接着会调用generateLayout方法为DecorView选择一个布局文件并通过addView的方式添加到DecorView中
  • WindowManager对DecorView的添加是在ActivityThread的handleResumeActivity方法中
wm.addView(decor, l);

Dialog与Window

  • Dialog中的PhoneWindow对象时在构造函数中初始化的
  • 在Dialog的setContentView中会调用window的setContentView方法完成对DecorView的初始化,并将布局添加到DecorView中
  • 在Dialog的show方法中会将DecorView通过WindowManager添加到Window中

Dialog属于子Window,所以在初始化Dialog的时候传入的context对象必须是Activity的,如果是Application的则会报错。

可以调用Dialog的getWindow方法得到Window对象,然后设置Window对象的type为系统类型,这种情况下就可以使用Application的context了(前提是需要声明权限)

Toast与Window

  • Toast中的Window是属于系统级别的
  • Toast中的视图是通过setView方法来决定的,平时使用的
Toast.makeText(this,"显示的内容",Toast.LENGTH_LONG).show();

是因为makeText方法内部会加载一个默认的布局,最终都是将布局赋值给Toast的mNextView成员变量

  • Toast类中并没有像Activity、Dialog那样体现Window这个对象

Activity、Dialog中Window对象的作用貌似就是通过Window对象的setContentView方法将布局设置给DecorView对象,然后在合适的时机通过WindowManager对象的addView方法将DecorView添加进Window,Toast中最后通过WindowManager添加的view是mNextView

  • Toast的show()方法内部是通过IPC调用了NotificationManagerService中的enqueueToast方法并将TN对象传给了它(TN对象时Toast对象的一个内部类),enqueueToast方法讲过一系列的判断之后调用TN对象中的show方法
  • Toast的show和cancel最终都是回调到了TN对象,由TN对象负责显示和隐藏
  • TN对象的show方法中会调用WindowManager的addView方法

相关文章

网友评论

      本文标题:Window相关(艺术探索读书笔记)

      本文链接:https://www.haomeiwen.com/subject/pgfiqctx.html