Activity、Window、View三者关系
目录介绍
- 01.Window,View,子Window
- 02.什么是Activity
- 03.什么是Window
- 04.什么是DecorView
- 05.什么是View
- 06.关系结构图
- 07.Window创建过程
- 08.创建机制分析
- 8.1 Activity实例的创建
- 8.2 Activity中Window的创建
- 8.3 DecorView的创建
弹窗系列博客
- 01.Activity、Window、View三者关系
- 深入分析Activity、Window、View三者之间的关系
- 02.Toast源码深度分析
- 最简单的创建,简单改造避免重复创建,show()方法源码分析,scheduleTimeoutLocked吐司如何自动销毁的,TN类中的消息机制是如何执行的,普通应用的Toast显示数量是有限制的,用代码解释为何Activity销毁后Toast仍会显示,Toast偶尔报错Unable to add window是如何产生的,Toast运行在子线程问题,Toast如何添加系统窗口的权限等等
- 03.DialogFragment源码分析
- 最简单的使用方法,onCreate(@Nullable Bundle savedInstanceState)源码分析,重点分析弹窗展示和销毁源码,使用中show()方法遇到的IllegalStateException分析
- 04.Dialog源码分析
- AlertDialog源码分析,通过AlertDialog.Builder对象设置属性,Dialog生命周期,Dialog中show方法展示弹窗分析,Dialog的dismiss销毁弹窗,Dialog弹窗问题分析等等
- 05.PopupWindow源码分析
- 显示PopupWindow,注意问题宽和高属性,showAsDropDown()源码,dismiss()源码分析,PopupWindow和Dialog有什么区别?为何弹窗点击一下就dismiss呢?
- 06.Snackbar源码分析
- 最简单的创建,Snackbar的make方法源码分析,Snackbar的show显示与点击消失源码分析,显示和隐藏中动画源码分析,Snackbar的设计思路,为什么Snackbar总是显示在最下面
- 07.弹窗常见问题
- DialogFragment使用中show()方法遇到的IllegalStateException,什么常见产生的?Toast偶尔报错Unable to add window,Toast运行在子线程导致崩溃如何解决?
- 09.onAttachedToWindow和onDetachedFromWindow
- onAttachedToWindow的调用过程,onDetachedFromWindow可以做什么?
- 10.DecorView介绍
- 什么是DecorView,DecorView的创建,DecorView的显示,深度解析
01.Window,View,子Window
- 弹窗有哪些类型
- 使用子窗口:在 Android 进程内,我们可以直接使用类型为子窗口类型的窗口。在 Android 代码中的直接应用是 PopupWindow 或者是 Dialog 。这当然可以,不过这种窗口依赖于它的宿主窗口,它可用的条件是你的宿主窗口可用
- 采用View系统:使用 View 系统去模拟一个窗口行为,且能更加快速的实现动画效果,比如SnackBar 就是采用这套方案
- 使用系统窗口:比如吐司Toast
02.什么是Activity
- Activity并不负责视图控制,它只是控制生命周期和处理事件。真正控制视图的是Window。一个Activity包含了一个Window,Window才是真正代表一个窗口。
- Activity就像一个控制器,统筹视图的添加与显示,以及通过其他回调方法,来与Window、以及View进行交互。
03.什么是Window
- Window是什么?
- 表示一个窗口的概念,是所有View的直接管理者,任何视图都通过Window呈现(点击事件由Window->DecorView->View; Activity的setContentView底层通过Window完成)
- Window是一个抽象类,具体实现是PhoneWindow。PhoneWindow中有个内部类DecorView,通过创建DecorView来加载Activity中设置的布局
R.layout.activity_main
。 - 创建Window需要通过WindowManager创建,通过WindowManager将DecorView加载其中,并将DecorView交给ViewRoot,进行视图绘制以及其他交互。
- WindowManager是外界访问Window的入口
- Window具体实现位于WindowManagerService中
- WindowManager和WindowManagerService的交互是通过IPC完成
- 如何通过WindowManager添加Window(代码实现)?
- 如下所示
//1. 控件
Button button = new Button(this);
button.setText("Window Button");
//2. 布局参数
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, 0, 0, PixelFormat.TRANSPARENT);
layoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED;
layoutParams.gravity = Gravity.LEFT | Gravity.TOP;
layoutParams.x = 100;
layoutParams.y = 300;
// 必须要有type不然会异常: the specified window type 0 is not valid
layoutParams.type = WindowManager.LayoutParams.TYPE_SYSTEM_ERROR;
//3. 获取WindowManager并添加控件到Window中
WindowManager windowManager = getWindowManager();
windowManager.addView(button, layoutParams);
- 如下所示
- WindowManager的主要功能是什么?
- 添加、更新、删除View
public interface ViewManager{
public void addView(View view, ViewGroup.LayoutParams params);
//添加View
public void updateViewLayout(View view, ViewGroup.LayoutParams params);
//更新View
public void removeView(View view);
//删除View
}
- 添加、更新、删除View
04.什么是DecorView
- DecorView是FrameLayout的子类,它可以被认为是Android视图树的根节点视图。
- DecorView作为顶级View,一般情况下它内部包含一个竖直方向的LinearLayout,在这个LinearLayout里面有上下三个部分,上面是个ViewStub,延迟加载的视图(应该是设置ActionBar,根据Theme设置),中间的是标题栏(根据Theme设置,有的布局没有),下面的是内容栏。
- 具体情况和Android版本及主体有关,以其中一个布局为例,如下所示:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:fitsSystemWindows="true"
android:orientation="vertical">
<!-- Popout bar for action modes -->
<ViewStub
android:id="@+id/action_mode_bar_stub"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inflatedId="@+id/action_mode_bar"
android:layout="@layout/action_mode_bar"
android:theme="?attr/actionBarTheme" /> <FrameLayout
style="?android:attr/windowTitleBackgroundStyle"
android:layout_width="match_parent"
android:layout_height="?android:attr/windowTitleSize"> <TextView
android:id="@android:id/title"
style="?android:attr/windowTitleStyle"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@null"
android:fadingEdge="horizontal"
android:gravity="center_vertical" />
</FrameLayout> <FrameLayout
android:id="@android:id/content"
android:layout_width="match_parent"
android:layout_height="0dip"
android:layout_weight="1"
android:foreground="?android:attr/windowContentOverlay"
android:foregroundGravity="fill_horizontal|top" />
</LinearLayout>
- 在Activity中通过setContentView所设置的布局文件其实就是被加到内容栏之中的,成为其唯一子View,就是上面的id为content的FrameLayout中,在代码中可以通过content来得到对应加载的布局。
ViewGroup content = (ViewGroup)findViewById(android.R.id.content);
ViewGroup rootView = (ViewGroup) content.getChildAt(0);
06.关系结构图
- Activity 与 PhoneWindow 与 DecorView 关系图
07.Window创建过程
- App点击桌面图片启动过程
- window启动流程
- Activity 与 PhoneWindow 与 DecorView 之间什么关系?
- 一个 Activity 对应一个 Window 也就是 PhoneWindow,一个 PhoneWindow 持有一个 DecorView 的实例,DecorView 本身是一个 FrameLayout。
08.创建机制分析
8.1 Activity实例的创建
- ActivityThread中执行performLaunchActivity,从而生成了Activity的实例。源码如下所示,ActivityThread类中源码
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
} catch (Exception e) {
...
} try {
...
if (activity != null) {
...
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor);
...
}
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
...
} return activity;
}
8.2 Activity中Window的创建
- 从上面的performLaunchActivity可以看出,在创建Activity实例的同时,会调用Activity的内部方法attach
- 在attach该方法中完成window的初始化。源码如下所示,Activity类中源码
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, ActivityConfigCallback activityConfigCallback) { mWindow = new PhoneWindow(this, window, activityConfigCallback);
mWindow.setWindowControllerCallback(this);
mWindow.setCallback(this);
mWindow.setOnWindowDismissedCallback(this);
mWindow.getLayoutInflater().setPrivateFactory(this);
if (info.softInputMode != WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED) {
mWindow.setSoftInputMode(info.softInputMode);
}
if (info.uiOptions != 0) {
mWindow.setUiOptions(info.uiOptions);
}
}
8.3 DecorView的创建
- 用户执行Activity的setContentView方法,内部是调用PhoneWindow的setContentView方法,在PhoneWindow中完成DecorView的创建。流程
- 1.Activity中的setContentView
- 2.PhoneWindow中的setContentView
- 3.PhoneWindow中的installDecor
public void setContentView(@LayoutRes int layoutResID) {
getWindow().setContentView(layoutResID);
initWindowDecorActionBar();
} @Override
public void setContentView(int layoutResID) {
...
if (mContentParent == null) {
installDecor();
} else if (!hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
mContentParent.removeAllViews();
}
...
} private void installDecor() {
if (mDecor == null) {
mDecor = generateDecor();
mDecor.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mDecor.setIsRootNamespace(true);
if (!mInvalidatePanelMenuPosted && mInvalidatePanelMenuFeatures != 0) {
mDecor.postOnAnimation(mInvalidatePanelMenuRunnable);
}
}
...
}
关于其他内容介绍
01.关于博客汇总链接
02.关于我的博客
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yczbj/activities
- 简书:http://www.jianshu.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
- 开源中国:https://my.oschina.net/zbj1618/blog
- 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 邮箱:yangchong211@163.com
- 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
- 掘金:https://juejin.im/user/5939433efe88c2006afa0c6e
GitHub链接:https://github.com/yangchong211
Activity、Window、View三者关系的更多相关文章
- Activity Window View的关系
http://blog.csdn.net/chiuan/article/details/7062215 http://blog.163.com/fenglang_2006/blog/static/13 ...
- 底层剖析 Window 、Activity、 View 三者关系
不管工作几年的 Android 工程师,或多或少都听说过 Window 的概念,并且隐隐约约感觉它在 Activity 与 View 之间应该发挥着某种连接的作用.但是如果需要说出这 3 者之间的关系 ...
- Activity Window View WindowManager关系&Touch事件分发机制
http://www.cnblogs.com/linjzong/p/4191891.html https://www.cnblogs.com/kest/p/5141817.html https://b ...
- activity window view 关系
1.Activity , Window和View的关系是什么? 跟踪Activity的源码就会发现:Activity.attch() -> PolicyManager -> Policy ...
- android中activity,window,view之间的关系
activity:控制单元 window:承载模型 view:显示视图 几个小tip: 1.一个 Activity 构造的时候一定会构造一个 Window(PhoneWindow),并且只有一个 2. ...
- android 中的 window,view,activity具体关系
通过讨论这个问题,我们能够见识到google是对面向对象模式的理解,能够理解android底层的一些调用.这也是一道很常见的面试题. 我们这篇文章就来解决这四个问题: Android 中view的显 ...
- Activity、Window和View三者间的关系有一定的见解
一.简述如何将Activity展现在手机上 Tips: Activity本身是没办法处理显示什么控件(view)的,是通过PhoneWindow进行显示的 换句话说:activity就是在造Phone ...
- 动态加载Layout 与 论Activity、 Window、View的关系
1)动态加载Layout的代码是 getWindow().setContentView(LayoutInflater.from(this).inflate(R.layout.main, null)); ...
- 动态载入Layout 与 论Activity、 Window、View的关系
1)动态载入Layout的代码是 getWindow().setContentView(LayoutInflater.from(this).inflate(R.layout.main, null)); ...
- View, Activity, Window
View, Activity, Window 2010-03-02 10:42:56| 分类: android|举报|字号 订阅 对于屏幕显示而言,整个是window,这个window里显示 ...
随机推荐
- crontab 里如何创建带日期的日志文件
需求在crontab 执行定时任务时,将执行的任务输出到带日期的文件中 crontab中,执行脚本需要传入系统时间date +"%Y-%m-%d" 问题今天遇到一个crontab问 ...
- [MyArch]我的Archlinux与bspwm的重生之途
0x00 前言碎语 2023.8.19 好久不见.这些日子一直在和bspwm和archlinux打交道.自从上次NepCTF的前几天和CuB3y0nd小师傅的bspwm配置打交道之后我一发不可收拾.中 ...
- NOI 2019 补全记录
D1T1 回家路线 好久之前写的,忘了具体细节,但是发现有平方项所以考虑拆项之后斜率优化. D1T2 机器人 考虑 DP. 记 \(f_{l,r,i}\) 表示 \([l,r]\) 这段区间,最大值为 ...
- MFC-ODBC API动态连接配置数据库
一.ODBC管理器介绍 在Window中,ODBC数据远管理器有6个标签:用户DSN.系统DSN.文件DSN.驱动程序.跟踪.连接池,通常情况下,使用用户DSN或者系统DSN,这里主要了解用户DSN和 ...
- STC89C52控制74HC595,74HC138双色16x16点阵屏循环显示汉字
简介 常见的LED点阵除了使用MAX7219, 还有一部分是使用74HC595, 前者能主动刷新, 后者需要上位机主动扫描刷新. 手里这块是德飞莱的16x16LED点阵模块, 板上印的型号LY-LED ...
- 【Unity3D】导航系统
1 导航系统简介 导航系统用于智能避障并寻找目标物体,如:王者荣耀中,当玩家跑到敌方塔的攻击范围内,敌方塔就会发射火团攻击玩家,当玩家逃跑时,火团会智能跟随玩家,其中智能跟随就使用到了导航系统. ...
- 【framework】View添加过程
1 前言 WMS启动流程 中介绍了 WindowManagerService 的启动流程,本文将介绍 View 的添加流程,按照进程分为以下2步: 应用进程:介绍从 WindowManagerImpl ...
- Spring Boot学生信息管理系统项目实战-1.项目介绍
1.获取源码 需要源码的朋友,请捐赠任意金额后留下邮箱发送:) 2.项目背景 刚开始自己帮教师朋友写的,核心是学生信息的导入导出功能.后来又扩展了几个模块. 水平一般能力有限,觉着有用的朋友可以拿去自 ...
- 使用ORACLE外部表装载复杂数据
原文:http://www.oracle.com/technetwork/issue-archive/2013/13-jan/o13asktom-1886639.html I am using SQL ...
- 02-Redis系列之-架构和高级API的使用
通用部分 通用命令 # 1-keys # 打印出所有key keys * # 打印出所有以n开头的key keys n* # 打印出所有以nam开头,第四个字母是a到z的范围 keys nam[a-z ...