Android WindowContainer窗口结构
Android窗口是根据显示屏幕来管理,每个显示屏幕的窗口层级分为37层,0-36层。每层可以放置多个窗口,上层窗口覆盖下面的。
要理解窗口的结构,需要学习下WindowContainer、RootWindowContainer、DisplayContent、TaskDisplayArea、Task、ActivityRecord、WindowToken、WindowState
WindowContainer等类。
WindowContainer类
为直接包含窗口或者通过孩子层级形式包含窗口的类,定义了普遍功能。它作为基类被继承,像RootWindowContainer、DisplayContent、TaskDisplayArea、Task、ActivityRecord、WindowToken、WindowState都是直接或间接的继承该类。
class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable {……// List of children for this window container. List is in z-order as the children appear on// screen with the top-most window container at the tail of the list.protected final WindowList<E> mChildren = new WindowList<E>(); ……}
窗口结构层级相关类
先上一张没添加特色模式窗口结构图:

该图是未添加特色模式时的结构图,添加特色模式之后的结构,更复杂。
RootWindowContainer:根窗口容器,树的根是它。通过它遍历寻找,可以找到窗口树上的窗口。它的孩子是DisplayContent。
DisplayContent:该类是对应着显示屏幕的,Android是支持多屏幕的,所以可能存在多个DisplayContent对象。上图只画了一个对象的结构,其他对象的结构也是和画的对象的结构是相似的。
TaskDisplayArea:它为DisplayContent的孩子,对应着窗口层次的第2层。第2层作为应用层,看它的定义:int APPLICATION_LAYER = 2,应用层的窗口是处于第2层。TaskDisplayArea的孩子是Task类,其实它的孩子类型也可以是TaskDisplayArea。而Task的孩子则可以是ActivityRecord,也可以是Task。
Tokens:它为DisplayContent的孩子,它的孩子是WindowToken。而WindowToken的孩子则为WindowState对象。WindowState是对应着一个窗口的。结构图中,DisplayContent不止包含一个Tokens,还有两个。其实ImeContainer也是继承自Tokens。
ImeContainer:它也为DisplayContent的孩子,它是输入法窗口的容器,它的孩子是WindowToken类型。WindowToken的孩子为WindowState类型,而WindowState类型则对应着输入法窗口。
Task:任务,它的孩子可以是Task,也可以是ActivityRecord类型。
ActivityRecord:是对应着应用进程中的Activity的。ActivityRecord是继承WindowToken的,它的孩子类型为WindowState。
WindowState:WindowState是对应着一个窗口的。
结构图中,DisplayContent有5个孩子。图中从上到下,第一个是Tokens,对应着窗口图层0、1。第二个是TaskDisplayArea,对应着窗口图层2。第三个是Tokens,对应着窗口图层3到14。第四个是ImeContainer,对应着窗口图层15到16。第五个是Tokens,对应着窗口图层17到36。
Activity添加窗口过程
@frameworks/base/core/java/android/app/ActivityOptions.java
ActivityOptions(Bundle opts) {private static final String KEY_AVOID_MOVE_TO_FRONT = "android.activity.avoidMoveToFront";mAvoidMoveToFront = opts.getBoolean(KEY_AVOID_MOVE_TO_FRONT, false);@frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
startActivityInnerSlog.w(TAG, "xww startActivityInner, targetTask=" + targetTask + " r=" + r + " sourceRecord=" + sourceRecord); //xww startActivityInner, targetTask=null r=ActivityRecord{44c341e u0 com.xxx.launcher/.MainActivity t2} sourceRecord=nullif (!mAvoidMoveToFront && mDoResume) { mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask); }
@frameworks/base/services/core/java/com/android/server/wm/Task.javamoveToFrontSlog.w(TAG, "xww moveToFront 3, task=" + task + " reason=" + reason); //xww moveToFront 3, task=null reason=reuseOrNewTaskmoveToFrontInner(reason, task);
@frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.javatask.getParent().positionChildAt(POSITION_TOP, task, true /* includingParents */);Slog.w(TAG, "xww positionChildAt 3aa, child.asTask()=" + child.asTask());//xww positionChildAt 3aa, child.asTask()=Task{7862cf6 #6 type=standard A=1000:com.xxx.launcher U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=1}positionChildTaskAt(position, child.asTask(), includingParents);if (includingParents && getParent() != null && (moveToTop || moveToBottom)) {Slog.w(TAG, "xww positionChildAt 6, this=" + this + " getParent()=" + getParent().toString());getParent().positionChildAt(moveToTop ? POSITION_TOP : POSITION_BOTTOM, this /* child */, true /* includingParents */);
@frameworks/base/services/core/java/com/android/server/wm/DisplayArea.javaif (includingParents && parent != null && (position == POSITION_TOP || position == POSITION_BOTTOM)) {Slog.w(TAG, "xww positionChildAt 18, this=" + this);parent.positionChildAt(position, this /* child */, true /* includingParents */);
@frameworks/base/services/core/java/com/android/server/wm/WindowContainer.javacase POSITION_TOP: Slog.w(TAG, "xww addChild 4 child=" + child.toString() + " position=" + position + " this=" + this.toString());mChildren.add(child); //ww addChild 4 child=Display{#2 state=ON size=1920x1080 ROTATION_0 name=avd_launcher} position=2147483647 this=com.android.server.wm.RootWindowContainer@973f7ec
@frameworks/base/services/core/java/com/android/server/wm/Task.java mTargetRootTask.startActivityLocked(mStartActivity, topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask, isTaskSwitch, mOptions, sourceRecord);if (!r.mLaunchTaskBehind && allowMoveToFront && (!isOrhasTask || newTask)) { positionChildAtTop(rTask);
@frameworks/base/services/core/java/com/android/server/wm/Task.java moveToFront("positionChildAtTop");@frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
populateInputWindowHandle
@frameworks/base/services/core/java/com/android/server/wm/WindowContainer.javafinal boolean focusable = w.canReceiveKeys() && (mService.mPerDisplayFocusEnabled || mDisplayContent.isOnTop());Slog.w(TAG, "xww isOnTop 3, this=" + toString() + " parent=" + (parent == null ? "null" : parent.toString()) + " parent.getTopChild()=" + (parent.getTopChild() == null ? "null" : parent.getTopChild().toString()));if(parent != null){for (int i = parent.mChildren.size() - 1; i >= 0; --i) {Object child = parent.mChildren.get(i);Slog.w(TAG, "xww isOnTop, i=" + i + ", child=" + child.toString());}} return parent != null && parent.getTopChild() == this && parent.isOnTop();//isOnTop 3, this=Display{#3 state=ON size=1920x1080 ROTATION_0 name=avd_launcher} parent=com.android.server.wm.RootWindowContainer@bf43992 parent.getTopChild()=Display{#3 state=ON size=1920x1080 ROTATION_0 name=avd_launcher}
@frameworks/base/services/core/java/com/android/server/wm/WindowList.java return mChildren.peekLast();return size() > 0 ? get(size() - 1) : null;
@frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.javaparent.isOnTop() //parent=com.android.server.wm.RootWindowContainer@bf43992return true;
addWindowToken流程
@frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java
addWindowToken
@frameworks/base/services/core/java/com/android/server/wm/WindowContainer.javada.addChild(token);Slog.w(TAG, "xww addChild 2 child=" + child.toString() + " this=" + this.toString()); //xww addChild 2 child=WindowToken{a0b2c76 android.os.Binder@9f68311} this=Leaf:3:14@132637315mChildren.add(positionToAdd, child);@frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
addChildSlog.w(TAG, "xww addChild 3 child=" + child.toString() + " index=" + index + " this=" + this.toString());mChildren.add(index, child);
打印窗口信息
@frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java void FindChildInfo(E node, String indent){Slog.w(TAG, "FindMeshInfo: node=" + indent + "|--" + node + ", size=" + node.mChildren.size());if(node.mChildren.size() == 0){return;}}void FindChild(E node, String indent){indent += "| ";FindChildInfo(node, indent);for(int i = 0; i < node.mChildren.size(); i++){FindChild((E)node.mChildren.get(i), indent);}}@frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
positionChildAtswitch (position) {case POSITION_TOP:if(child.toString().contains("avd_launcher")){String str = new String();Slog.w(TAG, "xww addChild xxxxx begin");this.FindChild((E)this, str);Slog.w(TAG, "xww addChild xxxxx end");}
FindMeshInfo: node=| |--com.android.server.wm.RootWindowContainer@58ef5a3, size=xxxFindMeshInfo: node=| | |--Display{#4 state=ON size=1920x1080 ROTATION_0 name=avd_launcher}, size=4FindMeshInfo: node=| | | |--WindowedMagnification:0:31@251785581, size=7FindMeshInfo: node=| | | | |--FullscreenMagnification:0:14@45167010, size=3FindMeshInfo: node=| | | | | |--Leaf:0:1@131968563, size=0FindMeshInfo: node=| | | | | |--DefaultTaskDisplayArea@48817648, size=1FindMeshInfo: node=| | | | | | |--Task{e9e1c50 #8 type=standard A=1000:com.xxx.launcher U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=1}, size=1FindMeshInfo: node=| | | | | | | |--ActivityRecord{bd29e49 u0 com.xxx.launcher/.MainActivity t8}, size=0FindMeshInfo: node=| | | | | |--Leaf:3:14@182007657, size=0FindMeshInfo: node=| | | | |--ImePlaceholder:15:16@26527214, size=1FindMeshInfo: node=| | | | | |--ImeContainer@79362703, size=0FindMeshInfo: node=| | | | |--FullscreenMagnification:17:23@93221148, size=1FindMeshInfo: node=| | | | | |--Leaf:17:23@197452069, size=0FindMeshInfo: node=| | | | |--Leaf:24:25@118182650, size=0FindMeshInfo: node=| | | | |--FullscreenMagnification:26:27@175550635, size=1FindMeshInfo: node=| | | | | |--Leaf:26:27@228557576, size=0FindMeshInfo: node=| | | | |--Leaf:28:28@117926561, size=0FindMeshInfo: node=| | | | |--FullscreenMagnification:29:31@170632390, size=1FindMeshInfo: node=| | | | | |--Leaf:29:31@133016711, size=0FindMeshInfo: node=| | | |--Leaf:32:32@36554676, size=0FindMeshInfo: node=| | | |--FullscreenMagnification:33:35@160370653, size=1FindMeshInfo: node=| | | | |--Leaf:33:35@179128146, size=0FindMeshInfo: node=| | | |--Leaf:36:36@49187363, size=0
@frameworks/base/core/java/android/app/ActivityOptions.java
ActivityOptions(Bundle opts) {
private static final String KEY_AVOID_MOVE_TO_FRONT = "android.activity.avoidMoveToFront";
mAvoidMoveToFront = opts.getBoolean(KEY_AVOID_MOVE_TO_FRONT, false);
@frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
startActivityInner
Slog.w(TAG, "xww startActivityInner, targetTask=" + targetTask + " r=" + r + " sourceRecord=" + sourceRecord); //xww startActivityInner, targetTask=null r=ActivityRecord{44c341e u0 com.xxx.launcher/.MainActivity t2} sourceRecord=null
if (!mAvoidMoveToFront && mDoResume) { mTargetRootTask.getRootTask().moveToFront("reuseOrNewTask", targetTask); }
@frameworks/base/services/core/java/com/android/server/wm/Task.java
moveToFront
Slog.w(TAG, "xww moveToFront 3, task=" + task + " reason=" + reason); //xww moveToFront 3, task=null reason=reuseOrNewTask
moveToFrontInner(reason, task);
@frameworks/base/services/core/java/com/android/server/wm/TaskDisplayArea.java
task.getParent().positionChildAt(POSITION_TOP, task, true /* includingParents */);
Slog.w(TAG, "xww positionChildAt 3aa, child.asTask()=" + child.asTask());
//xww positionChildAt 3aa, child.asTask()=Task{7862cf6 #6 type=standard A=1000:com.xxx.launcher U=0 visible=true visibleRequested=false mode=fullscreen translucent=true sz=1}
positionChildTaskAt(position, child.asTask(), includingParents);
if (includingParents && getParent() != null && (moveToTop || moveToBottom)) {
Slog.w(TAG, "xww positionChildAt 6, this=" + this + " getParent()=" + getParent().toString());
getParent().positionChildAt(moveToTop ? POSITION_TOP : POSITION_BOTTOM, this /* child */, true /* includingParents */);
@frameworks/base/services/core/java/com/android/server/wm/DisplayArea.java
if (includingParents && parent != null && (position == POSITION_TOP || position == POSITION_BOTTOM)) {
Slog.w(TAG, "xww positionChildAt 18, this=" + this);
parent.positionChildAt(position, this /* child */, true /* includingParents */);
@frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
case POSITION_TOP:
Slog.w(TAG, "xww addChild 4 child=" + child.toString() + " position=" + position + " this=" + this.toString());
mChildren.add(child); //ww addChild 4 child=Display{#2 state=ON size=1920x1080 ROTATION_0 name=avd_launcher} position=2147483647 this=com.android.server.wm.RootWindowContainer@973f7ec
@frameworks/base/services/core/java/com/android/server/wm/Task.java
mTargetRootTask.startActivityLocked(mStartActivity, topRootTask != null ? topRootTask.getTopNonFinishingActivity() : null, newTask, isTaskSwitch, mOptions, sourceRecord);
if (!r.mLaunchTaskBehind && allowMoveToFront && (!isOrhasTask || newTask)) { positionChildAtTop(rTask);
@frameworks/base/services/core/java/com/android/server/wm/Task.java
moveToFront("positionChildAtTop");
@frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java
populateInputWindowHandle
@frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
final boolean focusable = w.canReceiveKeys() && (mService.mPerDisplayFocusEnabled || mDisplayContent.isOnTop());
Slog.w(TAG, "xww isOnTop 3, this=" + toString() + " parent=" + (parent == null ? "null" : parent.toString()) + " parent.getTopChild()=" + (parent.getTopChild() == null ? "null" : parent.getTopChild().toString()));
if(parent != null){
for (int i = parent.mChildren.size() - 1; i >= 0; --i) {
Object child = parent.mChildren.get(i);
Slog.w(TAG, "xww isOnTop, i=" + i + ", child=" + child.toString());
}
}
return parent != null && parent.getTopChild() == this && parent.isOnTop();
//isOnTop 3, this=Display{#3 state=ON size=1920x1080 ROTATION_0 name=avd_launcher} parent=com.android.server.wm.RootWindowContainer@bf43992 parent.getTopChild()=Display{#3 state=ON size=1920x1080 ROTATION_0 name=avd_launcher}
@frameworks/base/services/core/java/com/android/server/wm/WindowList.java
return mChildren.peekLast();
return size() > 0 ? get(size() - 1) : null;
@frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
parent.isOnTop() //parent=com.android.server.wm.RootWindowContainer@bf43992
return true;
@frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
void FindChildInfo(E node, String indent){
Slog.w(TAG, "FindMeshInfo: node=" + indent + "|--" + node + ", size=" + node.mChildren.size());
if(node.mChildren.size() == 0){
return;
}
}
void FindChild(E node, String indent){
indent += "| ";
FindChildInfo(node, indent);
for(int i = 0; i < node.mChildren.size(); i++){
FindChild((E)node.mChildren.get(i), indent);
}
}
@frameworks/base/services/core/java/com/android/server/wm/WindowContainer.java
positionChildAt
switch (position) {
case POSITION_TOP:
if(child.toString().contains("avd_launcher")){
String str = new String();
Slog.w(TAG, "xww addChild xxxxx begin");
this.FindChild((E)this, str);
Slog.w(TAG, "xww addChild xxxxx end");
}
相关文章:
Android WindowContainer窗口结构
Android窗口是根据显示屏幕来管理,每个显示屏幕的窗口层级分为37层,0-36层。每层可以放置多个窗口,上层窗口覆盖下面的。 要理解窗口的结构,需要学习下WindowContainer、RootWindowContainer、DisplayContent、TaskDisplayArea、T…...
创建一个新的 React Native 项目
之前一直使用 npx react-native init my_app 来创建 RN 项目, 但是新版本会报错: Need to install the following packages: react-native0.77.0 Ok to proceed? (y) y npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While resolving: unde…...
Linux vmstat 命令
作用 性能监控工具。 示例 vmstat 2 5:每 2 秒执行 1 次,共执行 5 次。 下列示例中加了 -w 80 参数增加显示长度,目的是对齐字段值,Ctrl C 可停止输出。 [rootlocalhost ~]# vmstat 2 -w 80 procs -----------------------me…...
2025年最新版1688平台图片搜索接口技术指南及Python实现
随着电商行业的蓬勃发展,1688作为国内领先的B2B交易平台,其商品搜索功能对于买家和卖家而言都至关重要。图片搜索作为其中的一种高级搜索方式,能够极大地提升用户的搜索体验和准确性。本文将详细介绍如何通过API接口实现1688平台的图片搜索功…...
基于A*算法与贝塞尔曲线的路径规划与可视化:从栅格地图到平滑路径生成
引言 在机器人导航、自动驾驶和游戏开发等领域,路径规划是一个核心问题。如何高效地找到从起点到终点的最优路径,并且确保路径的平滑性和安全性,是许多应用场景中的关键挑战。本文将介绍一种结合A算法和贝塞尔曲线的路径规划方法,并通过Pygame实现可视化。我们将从栅格地图…...
使用verilog 实现 cordic 算法 ----- 旋转模式
1-设计流程 ● 了解cordic 算法原理,公式,模式,伸缩因子,旋转方向等,推荐以下链接视频了解 cordic 算法。哔哩哔哩-cordic算法原理讲解 ● 用matlab 或者 c 实现一遍算法 ● 在FPGA中用 verilog 实现,注意…...
【css】width:100%;padding:20px;造成超出100%宽度的解决办法 - box-sizing的使用方法 - CSS布局
问题 修改效果 解决方法 .xx {width: 100%;padding: 0 20px;box-sizing: border-box; } 默认box-sizing: content-box下, width 内容的宽度 height 内容的高度 宽度和高度的计算值都不包含内容的边框(border)和内边距(padding&…...
贪心算法_翻硬币
蓝桥账户中心 依次遍历 不符合条件就反转 题目要干嘛 你就干嘛 #include <bits/stdc.h>#define endl \n using namespace std;int main() {ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); string s; cin >> s;string t; cin >> t;int ret 0;for ( i…...
vue开发06:前端通过webpack配置代理处理跨域问题
1.定义 在浏览器尝试请求不同源(域名、协议、端口号不同)的资源时,浏览器的同源策略会阻止这种跨域请求。(比如前端端口15500,后端端口5050,前端界面不可以直接调用5050端口) 2.解决方案 使用前…...
深入HBase——引入
引入 前面我们通过深入HDFS到深入MapReduce ,从设计和落地,去深入了解了大数据最底层的基石——存储与计算是如何实现的。 这个专栏则开始来看大数据的三驾马车中最后一个。 通过前面我们对于GFS和MapReduce论文实现的了解,我们知道GFS在数…...
2025年02月12日Github流行趋势
项目名称:data-formulator 项目地址url:https://github.com/microsoft/data-formulator 项目语言:TypeScript 历史star数:4427 今日star数:729 项目维护者:danmarshall, Chenglong-MS, apps/dependabot, mi…...
【落羽的落羽 数据结构篇】双向链表
文章目录 一、链表的分类二、双向链表1. 结构2. 申请一个新节点3. 尾部插入数据4. 头部插入数据5. 尾部删除数据6. 头部删除数据7. 在指定位置之后插入数据8. 删除指定位置节点9. 销毁链表 一、链表的分类 链表的分类实际上要从这三个方向分析:是否带头、单向还是双…...
Golang的并发编程问题解决思路
Golang的并发编程问题解决思路 一、并发编程基础 并发与并行 在计算机领域,“并发”和“并行”经常被混为一谈,但它们有着不同的含义。并发是指一段时间内执行多个任务,而并行是指同时执行多个任务。在 Golang 中,通过 goroutines…...
vsftpd 配置项说明
目录 一:vsftpd 配置文件说明二:vsftpd 服务和连接设置三:vsftpd 用户根目录管理四:vsftpd 匿名用户模式管理五:vsftpd 本地用户模式管理六: vsftpd 虚拟用户模式管理 一:vsftpd 配置文件说明 …...
剑指offer第2版:搜索算法(二分/DFS/BFS)
查找本质就是排除的过程,不外乎顺序查找、二分查找、哈希查找、二叉排序树查找、DFS/BFS查找 一、p39-JZ3 找出数组中重复的数字(利用特性) 数组中重复的数字_牛客题霸_牛客网 方法1:全部排序再进行逐个扫描找重复。 时间复杂…...
Pytorch与大模型有什么关系
PyTorch 是 深度学习领域最流行的框架之一,在大模型的训练、推理、优化等方面发挥了重要作用。 大模型(如 GPT、LLaMA、Stable Diffusion)大多是基于 PyTorch 进行开发和训练的。 1. PyTorch 在大模型中的作用 大模型(如 ChatGP…...
在 CentOS 上更改 SSH 默认端口以提升服务器安全性
🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall ︱vue3-element-admin︱youlai-boot︱vue-uniapp-template 🌺 仓库主页: GitCode︱ Gitee ︱ Github 💖 欢迎点赞 👍 收藏 ⭐评论 …...
PyTorch Lightning pytorch.loggers模块介绍
pytorch.loggers 是 PyTorch Lightning 提供的一个模块,用于集成多种日志记录工具,方便开发者在训练过程中记录和监控模型的性能指标、超参数等信息。日志记录器(Loggers)是 PyTorch Lightning 的重要组成部分,可以通过…...
2025年:边缘计算崛起下运维应对新架构挑战
一、引言 随着科技的飞速发展,2025年边缘计算正以前所未有的速度崛起,给运维行业带来了全新的架构挑战。在这个充满机遇与挑战的时代,美信时代公司的美信监控易运维管理软件成为运维领域应对这些挑战的有力武器。 二、边缘计算崛起带来的运维…...
什么是UV环形光源
UV环形光源是一种用于特定照明需求的设备,以下是其关键点: 定义 UV环形光源:发出紫外光的环形照明装置,常用于机器视觉、工业检测等领域。特点 均匀照明:环形设计确保光线均匀分布,减少阴影。 高亮度&…...
怎么理解 Spring Boot 的约定优于配置 ?
在传统的 Spring 开发中,大家可能都有过这样的经历:项目还没开始写几行核心业务代码,就已经在各种配置文件中耗费了大量时间。比如,要配置数据库连接,不仅要在 XML 文件里编写冗长的数据源配置,还要处理事务…...
学习总结2.14
深搜将题目分配,如果是两个题目,就可以出现左左,左右,右左,右右四种时间分配,再在其中找最小值,即是两脑共同处理的最小值 #include <stdio.h> int s[4]; int sum0; int brain[25][25]; …...
Electron 客户端心跳定时任务调度库调研文档 - Node.js 任务调度库技术调研文档
Electron 客户端心跳定时任务调度库调研文档 - Node.js 任务调度库技术调研文档 本文将对七个流行的定时任务调度库:node-cron、rxjs、bull、node-schedule、agenda、bree、cron。这些库都可以用来处理定时任务,但它们的特点和适用场景有所不同。我们将从…...
【学术投稿-第四届智能电网和绿色能源国际学术会议(ICSGGE 2025)】CSS基本选择器详解:掌握基础,轻松布局网页
可线上 官网:www.icsgge.org 时间:2025年2月28-3月2日 目录 前言 一、基本选择器简介 1. 元素选择器(Type Selector) 基本语法 示例 注意事项 2. 类选择器(Class Selector) 基本语法 示例 注意…...
singleTaskAndroid的Activity启动模式知识点总结
一. 前提知识 1.1. 任务栈知识 二. Activity启动模式的学习 2.1 standard 2.2 singleTop 2.3.singleTask 2.4.singleInstance 引言: Activity作为四大组件之一,也可以说Activity是其中最重要的一个组件,其负责调节APP的视图ÿ…...
Java Stream 全面解析
Java Stream 全面解析 Java 8 引入的 Stream API 提供了一种高效且声明式的方式来处理集合数据。Stream 允许你以函数式编程风格操作数据,支持并行处理,并且可以显著简化代码。下面我们将从 创建操作、中间操作 和 终端操作 三个方面进行全面深入的解析…...
OpenCV识别电脑摄像头中的圆形物体
思路步骤 初始化摄像头:使用cv2.VideoCapture打开电脑摄像头。处理每一帧图像:对摄像头捕获的每一帧图像进行处理,包括灰度化、高斯模糊、霍夫圆变换等操作。绘制圆形和圆心:如果检测到圆形,使用cv2.circle函数用黄线…...
如何在 Tomcat 中屏蔽错误报告
Tomcat 屏蔽错误信息 <h1>HTTP状态 400 - 错误的请求</h1><hr class"line" /><p><b>类型</b> 异常报告</p><p><b>消息</b> 在请求目标中找到无效字符。有效字符在RFC 7230和RFC 3986中定义</p>&…...
Vue 入门到实战 十
第10章 Vue Router 目录 10.1 什么是路由 10.2 Vue Router的安装 10.2.1 本地独立版本方法 10.2.2 CDN方法 10.2.3 NPM方法 10.2.4 命令行工具(Vue CLI)方法 10.3 Vue Router的基本用法 10.3.1 跳转与传参 10.3.2 配置路由 10.…...
jenkins-获取当前时间戳
一. 简述: 很多场景下,需要获取当前时间戳。 二. 使用方法: 1. 安装: 最简单的, 莫过于直接部署相关插件: Build Timestamp Plugin 2. 配置: 3. 使用: post {success {script…...
