Android 12系统源码_窗口管理(八)WindowConfiguration的作用

前言

在Android系统中WindowConfiguration这个类用于管理与窗口相关的设置,该类存储了当前窗口的显示区域、屏幕的旋转方向、窗口模式等参数,应用程序通过该类提供的信息可以更好的适配不同的屏幕布局和窗口环境,以提高用户体验。

一、类定义

frameworks/base/core/java/android/app/WindowConfiguration.java

public class WindowConfiguration implements Parcelable, Comparable<WindowConfiguration> {//包含装饰窗口在内的窗口显示区域private Rect mBounds = new Rect();//不包含装饰窗口在内的窗口显示区域private Rect mAppBounds;//可显示的最大区域private final Rect mMaxBounds = new Rect();//当前屏幕设备的旋转角度private int mRotation = ROTATION_UNDEFINED;//当前窗口模式private @WindowingMode int mWindowingMode;//屏幕窗口模式private @WindowingMode int mDisplayWindowingMode;/** @hide */@IntDef(prefix = { "WINDOWING_MODE_" }, value = {WINDOWING_MODE_UNDEFINED,//未定义WINDOWING_MODE_FULLSCREEN,//全屏WINDOWING_MODE_MULTI_WINDOW,//多窗口WINDOWING_MODE_PINNED,WINDOWING_MODE_SPLIT_SCREEN_PRIMARY,WINDOWING_MODE_SPLIT_SCREEN_SECONDARY,WINDOWING_MODE_FREEFORM,})public @interface WindowingMode {}//Activity的类型private @ActivityType int mActivityType;/** @hide */@IntDef(prefix = { "ACTIVITY_TYPE_" }, value = {ACTIVITY_TYPE_UNDEFINED,ACTIVITY_TYPE_STANDARD,ACTIVITY_TYPE_HOME,ACTIVITY_TYPE_RECENTS,ACTIVITY_TYPE_ASSISTANT,ACTIVITY_TYPE_DREAM,})public @interface ActivityType {}//窗口是否总是位于最上层private @AlwaysOnTop int mAlwaysOnTop;/** @hide */@IntDef(prefix = { "ALWAYS_ON_TOP_" }, value = {ALWAYS_ON_TOP_UNDEFINED,ALWAYS_ON_TOP_ON,ALWAYS_ON_TOP_OFF,})private @interface AlwaysOnTop {}
}

在这里插入图片描述
该类主要有以下几个关键属性:

  • mBounds: 屏幕尺寸
  • mAppBounds:不包含装饰窗口在内的窗口显示区域**(根据源码发现mAppBounds只排除了导航栏这个装饰窗口所在的区域,状态栏和输入法等装饰窗口所在的区域是被包含在内的)**
  • mMaxBounds:窗口可显示的最大区域
  • mRotation:当前屏幕设备的旋转角度
  • mWindowingMode:当前窗口的窗口模式,例如未定义、全屏、分屏、多窗口等
  • ActivityType:页面类型,例如未定义、标准、首页、最近任务等
  • mAlwaysOnTop:窗口是否总是位于最上层

二、WindowConfiguration的属性设置

2.1 Configuration类

WindowConfiguration在Android系统中基本都是作为Configuration类的内部属性出现的。

frameworks/base/core/java/android/content/res/Configuration.java

public final class Configuration implements Parcelable, Comparable<Configuration> {public final WindowConfiguration windowConfiguration = new WindowConfiguration();}

2.2 计算当前屏幕尺寸和当前窗口可显示的最大区域

这里我们主要是结合WMS模块的相关代码来分析WindowConfiguration的各个属性的来源;系统主要是通过DisplayContent的computeScreenConfiguration方法来计算当前屏幕对应的窗口配置信息的。

frameworks/base/services/core/java/com/android/server/wm/DisplayContent.java

class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer>implements WindowManagerPolicy.DisplayContentInfo {DisplayInfo computeScreenConfiguration(Configuration outConfig, int rotation) {final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);//屏幕旋转角度final int dw = rotated ? mBaseDisplayHeight : mBaseDisplayWidth;//屏幕宽度final int dh = rotated ? mBaseDisplayWidth : mBaseDisplayHeight;//屏幕高度//注释1,对屏幕的实际宽高进行存储outConfig.windowConfiguration.setMaxBounds(0, 0, dw, dh);outConfig.windowConfiguration.setBounds(outConfig.windowConfiguration.getMaxBounds());final int uiMode = getConfiguration().uiMode;//UI模式final DisplayCutout displayCutout = calculateDisplayCutoutForRotation(rotation).getDisplayCutout();//计算屏幕的显示切口//注释2,调用computeScreenAppConfiguration方法computeScreenAppConfiguration(outConfig, dw, dh, rotation, uiMode, displayCutout);...代码省略...   }}

在注释1处根据屏幕旋转角度和基本显示尺寸,确定屏幕的实际宽高,并将其存储到WindowConfiguration的mMaxBounds属性和mBounds属性中。
在注释2处将屏幕实际宽度、高度、旋转角度、UI模式、屏幕显示切口作为参数,调用computeScreenAppConfiguration方法计算当前窗口可显示的安全区域。

2.3 计算当前窗口可显示的安全区域

class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowContainer>implements WindowManagerPolicy.DisplayContentInfo {private final DisplayPolicy mDisplayPolicy;private void computeScreenAppConfiguration(Configuration outConfig, int dw, int dh,int rotation, int uiMode, DisplayCutout displayCutout) {//注释1,获取不包含系统装饰窗口的可显示屏幕区域final Point appSize = mDisplayPolicy.getNonDecorDisplaySize(dw, dh, rotation, uiMode, displayCutout);//注释2,获取不包含系统装饰窗口的可显示屏幕边界mDisplayPolicy.getNonDecorInsetsLw(rotation, dw, dh, displayCutout, mTmpRect);final int leftInset = mTmpRect.left;final int topInset = mTmpRect.top;//注释3,存储应用的可显示的安全区域outConfig.windowConfiguration.setAppBounds(leftInset /* left */, topInset /* top */,leftInset + appSize.x /* right */, topInset + appSize.y /* bottom */);//存储屏幕旋转角度outConfig.windowConfiguration.setRotation(rotation);//存储屏幕是横屏还是竖屏outConfig.orientation = (dw <= dh) ? ORIENTATION_PORTRAIT : ORIENTATION_LANDSCAPE;//屏幕像素密度final float density = mDisplayMetrics.density;final Point configSize = mDisplayPolicy.getConfigDisplaySize(dw, dh, rotation, uiMode,displayCutout);outConfig.screenWidthDp = (int) (configSize.x / density);outConfig.screenHeightDp = (int) (configSize.y / density);outConfig.compatScreenWidthDp = (int) (outConfig.screenWidthDp / mCompatibleScreenScale);outConfig.compatScreenHeightDp = (int) (outConfig.screenHeightDp / mCompatibleScreenScale);final boolean rotated = (rotation == ROTATION_90 || rotation == ROTATION_270);outConfig.compatSmallestScreenWidthDp = computeCompatSmallestWidth(rotated, uiMode, dw,dh);}}

frameworks/base/services/core/java/com/android/server/wm/DisplayPolicy.java

public class DisplayPolicy {Point getNonDecorDisplaySize(int fullWidth, int fullHeight, int rotation, int uiMode,DisplayCutout displayCutout) {int width = fullWidth;int height = fullHeight;int navBarReducedHeight = 0;int navBarReducedWidth = 0;//获取导航栏的位置final int navBarPosition = navigationBarPosition(fullWidth, fullHeight, rotation);if (hasNavigationBar()) {if (navBarPosition == NAV_BAR_BOTTOM) {navBarReducedHeight = getNavigationBarHeight(rotation, uiMode);} else if (navBarPosition == NAV_BAR_LEFT || navBarPosition == NAV_BAR_RIGHT) {navBarReducedWidth = getNavigationBarWidth(rotation, uiMode, navBarPosition);}}if (mExtraNavBarAlt != null) {final LayoutParams altBarParams = mExtraNavBarAlt.getLayoutingAttrs(rotation);final int altBarPosition = getAltBarPosition(altBarParams);if (altBarPosition == ALT_BAR_BOTTOM || altBarPosition == ALT_BAR_TOP) {if (altBarPosition == navBarPosition) {navBarReducedHeight = Math.max(navBarReducedHeight,getAltBarHeight(ITYPE_EXTRA_NAVIGATION_BAR));} else {navBarReducedHeight += getAltBarHeight(ITYPE_EXTRA_NAVIGATION_BAR);}} else if (altBarPosition == ALT_BAR_LEFT || altBarPosition == ALT_BAR_RIGHT) {if (altBarPosition == navBarPosition) {navBarReducedWidth = Math.max(navBarReducedWidth,getAltBarWidth(ITYPE_EXTRA_NAVIGATION_BAR));} else {navBarReducedWidth += getAltBarWidth(ITYPE_EXTRA_NAVIGATION_BAR);}}}//当前窗口的安全显示区域为屏幕宽高减去导航栏所在的区域height -= navBarReducedHeight;width -= navBarReducedWidth;//如果屏幕显示切口对象不为空,还要减去该区域if (displayCutout != null) {height -= displayCutout.getSafeInsetTop() + displayCutout.getSafeInsetBottom();width -= displayCutout.getSafeInsetLeft() + displayCutout.getSafeInsetRight();}return new Point(width, height);}public void getNonDecorInsetsLw(int displayRotation, int displayWidth, int displayHeight,DisplayCutout displayCutout, Rect outInsets) {outInsets.setEmpty();//系统存在导航栏if (hasNavigationBar()) {final int uiMode = mService.mPolicy.getUiMode();//获取导航栏的位置,最终返回的边界区域要去掉导航栏所在的区域int position = navigationBarPosition(displayWidth, displayHeight, displayRotation);if (position == NAV_BAR_BOTTOM) {outInsets.bottom = getNavigationBarHeight(displayRotation, uiMode);} else if (position == NAV_BAR_RIGHT) {outInsets.right = getNavigationBarWidth(displayRotation, uiMode, position);} else if (position == NAV_BAR_LEFT) {outInsets.left = getNavigationBarWidth(displayRotation, uiMode, position);}}if (mExtraNavBarAlt != null) {final LayoutParams extraNavLayoutParams =mExtraNavBarAlt.getLayoutingAttrs(displayRotation);final int position = getAltBarPosition(extraNavLayoutParams);if (position == ALT_BAR_BOTTOM) {outInsets.bottom = Math.max(outInsets.bottom,getAltBarHeight(ITYPE_EXTRA_NAVIGATION_BAR));} else if (position == ALT_BAR_RIGHT) {outInsets.right = Math.max(outInsets.right,getAltBarWidth(ITYPE_EXTRA_NAVIGATION_BAR));} else if (position == ALT_BAR_LEFT) {outInsets.left = Math.max(outInsets.left,getAltBarWidth(ITYPE_EXTRA_NAVIGATION_BAR));} else if (position == ALT_BAR_TOP) {outInsets.top = Math.max(outInsets.top,getAltBarHeight(ITYPE_EXTRA_NAVIGATION_BAR));}}//如果屏幕显示切口对象不为空,还要减去该区域if (displayCutout != null) {outInsets.left += displayCutout.getSafeInsetLeft();outInsets.top += displayCutout.getSafeInsetTop();outInsets.right += displayCutout.getSafeInsetRight();outInsets.bottom += displayCutout.getSafeInsetBottom();}}}

在注释1处调用DisplayPolicy的getNonDecorDisplaySize方法,获取不包含系统装饰窗口的可显示屏幕区域,将结果存放在类型为Point的appSize对象中,结合getNonDecorDisplaySize方法源码可以发现该方法只是去除了导航栏窗口所在的区域,另外如果有屏幕显示切口区域,还会去除屏幕显示切口区域。
在注释2处调用DisplayPolicy的getNonDecorInsetsLw方法,获取不包含系统装饰窗口的可显示屏幕边界,将结果存放在类型为Rect的mTmpRect对象中,结合getNonDecorInsetsLw方法源码可以发现该方法只是去除了导航栏窗口所在的区域,另外如果有屏幕显示切口区域,还会去除屏幕显示切口区域。
在注释3处会结合appSize和mTmpRect,将当前窗口可显示的安全区域存储到Configuration的WindowConfiguration中。

三、WindowConfiguration的作用

WindowConfiguration的toString方法包含了此类的所有关键信息。

public class WindowConfiguration implements Parcelable, Comparable<WindowConfiguration> {@Overridepublic String toString() {return "{ mBounds=" + mBounds+ " mAppBounds=" + mAppBounds+ " mMaxBounds=" + mMaxBounds+ " mWindowingMode=" + windowingModeToString(mWindowingMode)+ " mDisplayWindowingMode=" + windowingModeToString(mDisplayWindowingMode)+ " mActivityType=" + activityTypeToString(mActivityType)+ " mAlwaysOnTop=" + alwaysOnTopToString(mAlwaysOnTop)+ " mRotation=" + (mRotation == ROTATION_UNDEFINED? "undefined" : rotationToString(mRotation))+ "}";}public static String windowingModeToString(@WindowingMode int windowingMode) {switch (windowingMode) {case WINDOWING_MODE_UNDEFINED: return "undefined";case WINDOWING_MODE_FULLSCREEN: return "fullscreen";case WINDOWING_MODE_MULTI_WINDOW: return "multi-window";case WINDOWING_MODE_PINNED: return "pinned";case WINDOWING_MODE_SPLIT_SCREEN_PRIMARY: return "split-screen-primary";case WINDOWING_MODE_SPLIT_SCREEN_SECONDARY: return "split-screen-secondary";case WINDOWING_MODE_FREEFORM: return "freeform";}return String.valueOf(windowingMode);}public static String activityTypeToString(@ActivityType int applicationType) {switch (applicationType) {case ACTIVITY_TYPE_UNDEFINED: return "undefined";case ACTIVITY_TYPE_STANDARD: return "standard";case ACTIVITY_TYPE_HOME: return "home";case ACTIVITY_TYPE_RECENTS: return "recents";case ACTIVITY_TYPE_ASSISTANT: return "assistant";case ACTIVITY_TYPE_DREAM: return "dream";}return String.valueOf(applicationType);}public static String alwaysOnTopToString(@AlwaysOnTop int alwaysOnTop) {switch (alwaysOnTop) {case ALWAYS_ON_TOP_UNDEFINED: return "undefined";case ALWAYS_ON_TOP_ON: return "on";case ALWAYS_ON_TOP_OFF: return "off";}return String.valueOf(alwaysOnTop);}
}
//frameworks/base/core/java/android/view/Surface.java
public class Surface implements Parcelable {public static String rotationToString(int rotation) {switch (rotation) {case Surface.ROTATION_0: {return "ROTATION_0";}case Surface.ROTATION_90: {return "ROTATION_90";}case Surface.ROTATION_180: {return "ROTATION_180";}case Surface.ROTATION_270: {return "ROTATION_270";}default: {return Integer.toString(rotation);}}}
}

当我们调用如下方法

 Log.i(TAG, "getWindowInfo: config = " + getResources().getConfiguration());

或者通过dumpsys window windows导出当前所有窗口的堆栈信息,都可以得到和Configuration类相关的以下信息:

config={1.0 ?mcc?mnc [zh_CN] ldltr sw360dp w764dp h324dp 480dpi nrml long land finger -keyb/h/h -nav/h winConfig={ mBounds=Rect(0, 0 - 2400, 1080) mAppBounds=Rect(107, 0 - 2400, 1080) mMaxBounds=Rect(0, 0 - 2400, 1080) mDisplayRotation=ROTATION_90 mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATION_90} s.2 fontWeightAdjustment=0mThemeChanged= 0, mThemeChangedFlags= 0, mFlipFont= 0, mAccessibleChanged= -1, mUxIconConfig= 3468921665126662176, mMaterialColor= 0, mUserId= 0, mFontUserId= 0, mFontVariationSettings= 226, mFoldingAngle = -1.0, mIconPackName= , mDarkModeBackgroundMaxL= 0.0, mDarkModeDialogBgMaxL= 27.0, mDarkModeForegroundMinL= 100.0, mOplusConfigType= 1, mOplusChangedConfigs= 0, OpSans= 0, mBurmeseFontFlag= 2, mFlag= 0, mPuttDisplayFlag= -1}

这里我们重点关注和WindowConfiguration相关的信息:

winConfig={ mBounds=Rect(0, 0 - 2400, 1080) mAppBounds=Rect(107, 0 - 2400, 1080) mMaxBounds=Rect(0, 0 - 2400, 1080) mWindowingMode=fullscreen mDisplayWindowingMode=fullscreen mActivityType=standard mAlwaysOnTop=undefined mRotation=ROTATION_90}
  • mBounds=Rect(0, 0 - 2400, 1080):屏幕尺寸
  • mAppBounds=Rect(107, 0 - 2400, 1080):窗口可显示的安全区域,此属性会影响应用具体加载那个layout下面的布局文件,系统会优先选择尺寸最接近2293x1080的布局文件。
  • mMaxBounds=Rect(0, 0 - 2400, 1080):窗口可显示的最大区域
  • mWindowingMode=fullscreen:窗口为全屏模式
  • mDisplayWindowingMode=fullscreen:屏幕设备窗口为全屏模式
  • mActivityType=standard:页面类型未定义
  • mAlwaysOnTop=undefined:窗口悬浮模式未定义
  • mRotation=ROTATION_90:屏幕设备的旋转角度为90度

借助这些属性,开发者能够更好地适配不同的设备配置和屏幕状态,确保应用在不同环境下的一致性和优化。

四、修改WindowConfiguration的配置信息,刷新窗口UI视图

4.1 通过adb 修改屏幕旋转角度

我们可以通过以下指令获取当前屏幕的旋转角度

adb shell settings get system user_rotation #0:自然方向(竖屏)1:右旋转 90 度(横屏)2:倒转 180 度(反向竖屏)3:左旋转 270 (横屏)

还可以通过如下配置修改当前屏幕的旋转角度

adb shell settings put system user_rotation <value>

4.2 实现原理

当我们修改system数据库中的user_rotation字段的时候,会触发以下代码逻辑。

frameworks/base/services/core/java/com/android/server/wm/DisplayRotation.java

//frameworks/base/core/java/android/provider/Settings.java
public final class Settings {public static final String USER_ROTATION = "user_rotation";
}
public class DisplayRotation {private final WindowManagerService mService;private class SettingsObserver extends ContentObserver {SettingsObserver(Handler handler) {super(handler);}void observe() {final ContentResolver resolver = mContext.getContentResolver();...代码省略...//注释1,监听system数据库user_rotation字段的变化resolver.registerContentObserver(Settings.System.getUriFor(Settings.System.USER_ROTATION), false, this,UserHandle.USER_ALL);updateSettings();}@Overridepublic void onChange(boolean selfChange) {//注释2,判断设置是否发生了变化,如果发生了变化调用WMS的updateRotation方法if (updateSettings()) {mService.updateRotation(true /* alwaysSendConfiguration */,false /* forceRelayout */);}}}private boolean updateSettings() {final ContentResolver resolver = mContext.getContentResolver();boolean shouldUpdateRotation = false;synchronized (mLock) {...代码省略...//获取当前屏的旋转角度final int userRotation = Settings.System.getIntForUser(resolver,Settings.System.USER_ROTATION, Surface.ROTATION_0,UserHandle.USER_CURRENT);if (mUserRotation != userRotation) {mUserRotation = userRotation;shouldUpdateRotation = true;}...代码省略...return shouldUpdateRotation;}}

在注释1处DisplayRotation类会监听system数据库的user_rotation字段的变化,当该字段发生变化的时候,会在注释2处触发WindowManagerServices的updateRotation方法。

frameworksbase/services/core/java/com/android/server/wm/WindowManagerService.java

public class WindowManagerService extends IWindowManager.Stubimplements Watchdog.Monitor, WindowManagerPolicy.WindowManagerFuncs {@Overridepublic void updateRotation(boolean alwaysSendConfiguration, boolean forceRelayout) {updateRotationUnchecked(alwaysSendConfiguration, forceRelayout);}private void updateRotationUnchecked(boolean alwaysSendConfiguration, boolean forceRelayout) {...代码省略...try {synchronized (mGlobalLock) {boolean layoutNeeded = false;final int displayCount = mRoot.mChildren.size();for (int i = 0; i < displayCount; ++i) {final DisplayContent displayContent = mRoot.mChildren.get(i);Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "updateRotation: display");final boolean rotationChanged = displayContent.updateRotationUnchecked();Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);if (rotationChanged) {mAtmService.getTaskChangeNotificationController().notifyOnActivityRotation(displayContent.mDisplayId);}if (!rotationChanged || forceRelayout) {displayContent.setLayoutNeeded();layoutNeeded = true;}if (rotationChanged || alwaysSendConfiguration) {displayContent.sendNewConfiguration();}}if (layoutNeeded) {Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,"updateRotation: performSurfacePlacement");mWindowPlacerLocked.performSurfacePlacement();Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}}} finally {Binder.restoreCallingIdentity(origId);Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/422525.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何基于gpt模型抢先打造成功的产品

来自&#xff1a;Python大数据分析 费弗里 ChatGPT、gpt3.5以及gpt4&#xff0c;已然成为当下现代社会中几乎人尽皆知的话题&#xff0c;而当此种现象级产品引爆全网&#xff0c;极大程度上吸引大众注意力的同时&#xff0c;有一些嗅觉灵敏的人及时抓住了机会&#xff0c;通过快…

SpringBoot2:web开发常用功能实现及原理解析-上传与下载

文章目录 一、上传文件1、前端上传文件给Java接口2、Java接口上传文件给Java接口 二、下载文件1、前端从Java接口下载文件2、Java接口调用Java接口下载文件 一、上传文件 1、前端上传文件给Java接口 Controller接口 此接口支持上传单个文件和多个文件&#xff0c;并保存在本地…

伙房食堂电气安全新挑战:油烟潮湿环境下,如何筑起电气火灾“防火墙”?

近几年&#xff0c;随着我国经济的飞速发展&#xff0c;食堂餐饮也经历了一场变革&#xff0c;越来越多的电器走进了伙房食堂中&#xff0c;实现了电气化&#xff0c;为人们提供了高效便利的饮食服务&#xff0c;但同时也增加了火灾负荷。目前我国非常严重的电气火灾危害&#…

IBM中国研发中心撤出:挑战与机遇并存

IBM中国研发中心撤出&#xff1a;挑战与机遇并存 引言 近日&#xff0c;IBM宣布撤出在中国的两大研发中心的消息&#xff0c;引起了广泛关注。这一举动不仅对IBM自身的全球布局产生了影响&#xff0c;也在一定程度上反映了跨国公司在中国市场策略的调整。本文将探讨这一事件背…

服务器重装Ubuntu20.04(desktop)

引言 实验室服务器因为删除了一些底层文件导致系统无法恢复&#xff08;还好没有数据有备份&#xff09;&#xff0c;所以在此告诫广大朋友&#xff0c;有一些底层文件不要说删就删。好的&#xff0c;接下来我们开始重装系统。 准备工作 准备好重装系统的材料如下&#xff1…

odoo14 | 报错:Database backup error: Access Denied

这两天抽空想为自己快速做一个简单的管理系统&#xff0c;来信息化管理一下自己家里的一些菜谱、电视剧下载清单等事情&#xff0c;我又不想大动干戈的用Java写管理系统&#xff0c;我就想用已经手生了两年半的odoo快速搭一个系统用用得了&#xff0c;结果还遇上了这么个事 根…

【数据结构与算法 | 灵神题单 | 插入链表篇】力扣2807, LCR 029, 147

1. 力扣2807&#xff1a;在链表中插入最大公约数 1.1 题目&#xff1a; 你一个链表的头 head &#xff0c;每个结点包含一个整数值。 在相邻结点之间&#xff0c;请你插入一个新的结点&#xff0c;结点值为这两个相邻结点值的 最大公约数 。 请你返回插入之后的链表。 两个…

大数据新视界 --大数据大厂之Flink强势崛起:大数据新视界的璀璨明珠

&#x1f496;&#x1f496;&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎你们来到 青云交的博客&#xff01;能与你们在此邂逅&#xff0c;我满心欢喜&#xff0c;深感无比荣幸。在这个瞬息万变的时代&#xff0c;我们每个人都在苦苦追寻一处能让心灵安然栖息的港湾。而 我的…

【网络安全】服务基础第二阶段——第四节:Linux系统管理基础----Linux网络与日志服务器

目录 一、Linux基础知识 1.1 Linux系统常用目录及命令 1.1.1 常用目录 1.1.2 常用命令 1.1.3 Linux系统文件和命令 1.1.3 文件操作 1.1.4 文件打包和压缩 1.1.5 Linux系统包管理 1.1.6 RPM命令 二、YUM 2.1 YUM 2.1.1 YUM工具 2.1.2 YUM配置 2.2 YUM源安装前置准…

机器人的静力分析与动力学

参考链接&#xff1a;4-13刚体的惯性张量_哔哩哔哩_bilibili4-13刚体的惯性张量, 视频播放量 6540、弹幕量 2、点赞数 79、投硬币枚数 38、收藏人数 145、转发人数 23, 视频作者 每一天都应不同, 作者简介 ROS1是DCS,ROS2是FCS&#xff0c;相关视频&#xff1a;机器人动力学拉格…

(八) 初入MySQL 【主从复制】

案例概况 在企业应用中&#xff0c;成熟的业务通常数据量都比较大 单台MySQL在安全性、 高可用性和高并发方面都无法满足实际的需求 &#xff0c;所以需要配置多台主从数据库服务器以实现读写分离来满足需求 一、主从复制原理 1.1、 MySQL的复制类型 基于语句的复制(STATEME…

从0开始的算法(数据结构和算法)基础(十一)

回溯算法 什么是回溯算法 回溯算法&#xff0c;根据字面意思来理解这个算法是将每一步的操作可以进行回溯&#xff0c;实际上是对这个每一步的操作进行记录&#xff0c;确保可以返回上一步的操作&#xff0c;可能是对回溯操作之前的做一个复现&#xff0c;也有可能是可操作的回…

神经网络中的那些浮点数

模型进行需要大量显存和算力进行支持&#xff0c;精度越高需要的内存和算力也越多&#xff0c;本文将介绍在模型中使用的不同类型的浮点数。 FP32 (Float32)&#xff1a; • 精度和稳定性&#xff1a;FP32 提供 23 位尾数和 8 位指数的高精度 • 性能&#xff1a;尽管 FP32 是通…

学习大数据DAY56 业务理解和第一次接入

作业1 1 了解行业名词 ERP CRM OA MES WMS RPA SAAS 了解每个系统的功能和应用 ERP 系统&#xff0c;&#xff08;Enterprise Resource Planning&#xff0c;企业资源计划系统&#xff09;&#xff1a;ERP 系统 是一种用于管理企业各类资源的软件系统&#xff0c;包括生产管理…

极狐GitLab CI/CD 作业一直处于等待状态,如何解决?

本分分享 GitLab CI/CD Job 不工作的的故障排查方法&#xff1a;当 GitLab Runner 不接受 Job&#xff0c;Job 一直处于等待状态&#xff0c;如何解决此问题。 极狐GitLab 为 GitLab 在中国的发行版&#xff0c;中文版本对中国用户更友好。极狐GitLab 支持一键私有化部署&…

【Hot100】LeetCode—72. 编辑距离

目录 1- 思路题目识别动规五部曲 2- 实现⭐72. 编辑距离——题解思路 3- ACM 实现 原题链接&#xff1a;72. 编辑距离 1- 思路 题目识别 识别1 &#xff1a;两个字符串之间相互转换&#xff0c;增、删、替换 最少的操作次数 动规五部曲 1- 定义 dp 数组 dp[i][j] 代表&…

如何增加Google收录量?

想增加Google收录量&#xff0c;首先自然是你的页面数量就要多&#xff0c;但这些页面的内容也绝对不能敷衍&#xff0c;你的网站都没多少页面&#xff0c;谷歌哪怕想收录都没办法&#xff0c;当然&#xff0c;这是一个过程&#xff0c;持续缓慢的增加页面&#xff0c;增加网站…

11.5.软件系统分析与设计-面向对象的程序设计与实现

面向对象的程序设计与实现 设计模式 Java代码 C代码

神经网络案例实践之单层感知器求解-学习篇

二维线性分类问题 单层感知器作为线性分类器被广泛应用 问题分析&#xff1a; 首先给了五个输入样本&#xff0c;输入样本和位置信息如下所示&#xff0c;现在要学习一个模型&#xff0c;在二维空间中把两个样本分开&#xff0c;输入数据是个矩阵&#xff0c;矩阵中有五个样本…

手写排班日历

手写排班日历&#xff1a; 效果图&#xff1a; vue代码如下&#xff1a; <template><div class"YSPB"><div class"title">排班日历</div><div class"banner"><span classiconfont icon-youjiantou click&qu…