您当前的位置: 首页 > 
  • 0浏览

    0关注

    674博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Dialog为何只能用Activity的Context

沙漠一只雕得儿得儿 发布时间:2021-03-24 19:53:43 ,浏览量:0

一个Dialog从无到有经历了以下几个步骤
  • 首先创建了一个新的Window,类型是PhoneWindow类型,与Activity创建Window过程类似,并设置 setCallback回调。

  • 将这个新Window与从Activity拿到的 WindowManager对象相关联,也就是dialog与Activity公用了同一个 WindowManager对象。

  • show方法展示Dialog,先回调了Dialog的 onCreate,onStart方法。

  • 然后获取Dialog自己的 DecorView对象,并通过addView方法添加到WindowManager对象中,Dialog出现到屏幕上。

分析这个流程我们还可以得知一些平时遇到的小问题,比如为啥Dialog必须要依附于Activity显示?因为Dialog创建过程中需要使用Activity的Context,即需要使用Activity的token用来创建window。所以传入Application的Content就会报错——“Unable to add window -- token null is not for an application”。

回到正题,这个过程用一句话总结就是,Dialog用了Activity的WindowManager对象,并在这之上添加了一个新的Window的DecorView

Context必须是Activity

dialog中windowManager的获取

mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

如果上述context是Application,实际调用的是ContextImpl.getSystemService,获取的WM是new WindowManagerImpl(display),即mParentWindow为null; 如果上述context是Activity,获取的WM是new WindowManagerImpl(mDisplay, parentWindow),这个parentWindow就是Activity里的PhoneWindow,且这个PhoneWindow设置了mAppToken。

在创建dialog时,如果传入构造方法不是一个activity类型的上下文,则导致WindowManagerImpl类型为Window的变量mParentWindow为null,从而导致WindowManagerGlobal的addView不会调用Window的adjustLayoutParamsForSubWindow方法,从而不会给attr.token赋值,导致在WindowManagerService服务中的身份验证失败,抛出BadTokenException异常。

可以看到只有parentWindow不为空才会走到adjustLayoutParamsForSubWindow方法中,

在adjustLayoutParamsForSubWindow方法中会有对token的保存,只有正确的token才能在后续的跨进程通信过程中完成信息的校验。

Token直译成中文是令牌的意思,android系统中将其作为一种安全机制,其本质是一个Binder对象,在跨进程的通行中充当验证码的作用。比如:在activity的启动过程及界面绘制的过程中会涉及到ActivityManagerService,应用程序,WindowManagerService三个进程间的通信,此时Token在这3个进程中充当一个身份验证的功能,ActivityManagerService与WindowManagerService通过应用程序的activity传过来的Token来分辨到底是控制应用程序的哪个activity。

参考:

https://www.jianshu.com/p/3a1b40f4de36

https://www.jianshu.com/p/413ec659500a

关注
打赏
1657159701
查看更多评论
立即登录/注册

微信扫码登录

0.0461s