Launcher3主页面加载显示流程分析
布局结构
抓取布局后,可以看到每个图标是一个DoubleShadowBubbleTextView,父布局是CellLayout、workspace。
我们可以在CellLayout添加子view打印出调用堆栈信息,可以整体上看页面加载显示流程。
主要类
- Launcher.java:主界面,即MainActivity
- launcher.xml:主界面布局文件
- LauncherModel.java:管理Launcher状态,包括加载任务、状态回调等
- LoaderTask.java:加载任务,是一个Runnable
- LoaderResults.java:加载结果
- BgDataModel#Callbacks:数据回调接口,Launcher实现该接口,加载任务通过该接口回调给Launcher
- LauncherProvider:桌面数据提供者,采用db保存桌面图标数据(包括排列位置、类型等)
- LauncherSettings:封装访问LauncherProvider时的uri、column等一些常量,通过ContentResolver来访问LauncherProvider,不直接操作db
- LoaderCursor:封装cursor操作
流程图
创建Activity
主界面创建的时候,常规的setContentView和findView,创建LauncherModel并开始加载数据
// Launcher.java
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 1.创建LauncherAppState和LauncherModelLauncherAppState app = LauncherAppState.getInstance(this);mModel = app.getModel();// 2.infalte布局文件,找到viewsetupViews();// 3. 设置loader监听,开始加载数据,加载完成后回调给主界面if (!mModel.addCallbacksAndLoad(this)) {if (!internalStateHandled) {// If we are not binding synchronously, pause drawing until initial bind complete,// so that the system could continue to show the device loading promptmOnInitialBindListener = Boolean.FALSE::booleanValue;}}// 4. 设置view给ActivitysetContentView(getRootView());
加载数据
创建加载任务
mModel.addCallbacksAndLoad将Launcher设置给LauncherModel,然后创建了加载任务
// LauncherModel.java
/*** Adds a callbacks to receive model updates* @return true if workspace load was performed synchronously*/
public boolean addCallbacksAndLoad(@NonNull final Callbacks callbacks) {synchronized (mLock) {addCallbacks(callbacks);return startLoader(new Callbacks[] { callbacks });}
}private boolean startLoader(@NonNull final Callbacks[] newCallbacks) {synchronized (mLock) {// 1.取消旧的加载任务boolean wasRunning = stopLoader(); // 之前没有loader任务,wasRunning为falseboolean bindDirectly = mModelLoaded && !mIsLoaderTaskRunning;// 之前没有加载过,bindDirectly为falseboolean bindAllCallbacks = wasRunning || !bindDirectly || newCallbacks.length == 0; // bindAllCallbacks为true, 上一步已经addCallbacks了,所以callbacksList里面包含从Launcher.java传进来的callbacksfinal Callbacks[] callbacksList = bindAllCallbacks ? getCallbacks() : newCallbacks;if (callbacksList.length > 0) {// 2.清空PendingBindfor (Callbacks cb : callbacksList) {MAIN_EXECUTOR.execute(cb::clearPendingBinds);}// 3.创建LoaderResults和LoaderTask,开始加载数据LoaderResults loaderResults = new LoaderResults(mApp, mBgDataModel, mBgAllAppsList, callbacksList);if (bindDirectly) {loaderResults.bindWorkspace(bindAllCallbacks);loaderResults.bindAllApps();loaderResults.bindDeepShortcuts();loaderResults.bindWidgets();return true;} else {stopLoader();mLoaderTask = new LoaderTask(mApp, mBgAllAppsList, mBgDataModel, mModelDelegate, loaderResults);MODEL_EXECUTOR.post(mLoaderTask);}}}
}
整体加载步骤
LoaderTask#run中根据类型加载步骤分为了5步,图标的加载主要看第一步
// LoaderTask.java
public void run() {try (LauncherModel.LoaderTransaction transaction = mApp.getModel().beginLoader(this)) {// first stepList<ShortcutInfo> allShortcuts = new ArrayList<>();loadWorkspace(allShortcuts, memoryLogger);// Sanitize data re-syncs widgets/shortcuts based on the workspace loaded from db.// sanitizeData should not be invoked if the workspace is loaded from a db different// from the main db as defined in the invariant device profile.// (e.g. both grid preview and minimal device mode uses a different db)if (mApp.getInvariantDeviceProfile().dbFile.equals(mDbName)) {sanitizeData();}mResults.bindWorkspace(true /* incrementBindId */);mModelDelegate.workspaceLoadComplete();// Notify the installer packages of packages with active installs on the first screen.sendFirstScreenActiveInstallsBroadcast();// Take a breakwaitForIdle();// second stepList<LauncherActivityInfo> allActivityList;allActivityList = loadAllApps();mResults.bindAllApps();IconCacheUpdateHandler updateHandler = mIconCache.getUpdateHandler();setIgnorePackages(updateHandler);updateHandler.updateIcons(allActivityList,LauncherActivityCachingLogic.newInstance(mApp.getContext()),mApp.getModel()::onPackageIconsUpdated);updateHandler.updateIcons(allShortcuts, new ShortcutCachingLogic(),mApp.getModel()::onPackageIconsUpdated);waitForIdle();// third stepList<ShortcutInfo> allDeepShortcuts = loadDeepShortcuts();mResults.bindDeepShortcuts();updateHandler.updateIcons(allDeepShortcuts,new ShortcutCachingLogic(), (pkgs, user) -> { });waitForIdle();// fourth stepList<ComponentWithLabelAndIcon> allWidgetsList =mBgDataModel.widgetsModel.update(mApp, null);mResults.bindWidgets();updateHandler.updateIcons(allWidgetsList,new ComponentWithIconCachingLogic(mApp.getContext(), true),mApp.getModel()::onWidgetLabelsUpdated);// fifth steploadFolderNames();updateHandler.finish();mModelDelegate.modelLoadComplete();transaction.commit();} catch (CancellationException e) {...}
}
图标解析
loadWorkspace()代码比较多,主要作用是通过ContentResolver查询LauncherProvider中保存的桌面图标信息,然后遍历cursor来解析数据。
在分析代码的时候,抓到数据流向,可以结合真实的db数据进行分析,其中一些判断容错处理可以跳过
主要流程如下:
- 加载默认的数据(Provider会有判断,只有第一次才会加载)
- 通过ContentResolver查询所有数据
- 遍历cursor,根据不同图标类型进行解析,如ITEM_TYPE_APPLICATION代表普通的图标,ITEM_TYPE_FOLDER代表文件夹
- 对数据进行一些校验,校验通过后将数据添加到mBgDataModel
数据流向:
Db(LauncherProvider) --> Cursor(LoaderCursor) --> List(BgDataModel)
protected void loadWorkspace(List<ShortcutInfo> allDeepShortcuts,Uri contentUri,String selection,@Nullable LoaderMemoryLogger logger) {final Context context = mApp.getContext();final ContentResolver contentResolver = context.getContentResolver();// 1. 加载默认的数据(Provider会有判断,只有第一次才会加载)LauncherSettings.Settings.call(contentResolver,LauncherSettings.Settings.METHOD_LOAD_DEFAULT_FAVORITES);synchronized (mBgDataModel) {mBgDataModel.clear();mPendingPackages.clear();// 2. 查询所有数据final LoaderCursor c = new LoaderCursor(contentResolver.query(contentUri, null, selection, null, null), contentUri,mApp, mUserManagerState);final Bundle extras = c.getExtras();mDbName = extras == null? null : extras.getString(LauncherSettings.Settings.EXTRA_DB_NAME);try {// 2.1 遍历cursorfinal int appWidgetIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_ID);final int appWidgetProviderIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_PROVIDER);final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);final int rankIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.RANK);final int optionsIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.OPTIONS);final int sourceContainerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_SOURCE);WorkspaceItemInfo info;LauncherAppWidgetInfo appWidgetInfo;LauncherAppWidgetProviderInfo widgetProviderInfo;Intent intent;String targetPkg;List<IconRequestInfo<WorkspaceItemInfo>> iconRequestInfos = new ArrayList<>();while (!mStopped && c.moveToNext()) {try {// 2.2 根据不同图标类型进行解析,ITEM_TYPE_APPLICATION代表普通的图标,ITEM_TYPE_FOLDER代表文件夹switch (c.itemType) {case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:intent = c.parseIntent();// 2.3 解析数据,进行一些校验判断if (info != null) {if (info.itemType!= LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT) {// Skip deep shortcuts; their title and icons have already been// loaded above.iconRequestInfos.add(c.createIconRequestInfo(info, useLowResIcon));}c.applyCommonProperties(info);info.intent = intent;info.rank = c.getInt(rankIndex);info.spanX = 1;info.spanY = 1;info.runtimeStatusFlags |= disabledState;if (isSafeMode && !isSystemApp(context, intent)) {info.runtimeStatusFlags |= FLAG_DISABLED_SAFEMODE;}LauncherActivityInfo activityInfo = c.getLauncherActivityInfo();if (activityInfo != null) {info.setProgressLevel(PackageManagerHelper.getLoadingProgress(activityInfo),PackageInstallInfo.STATUS_INSTALLED_DOWNLOADING);}if (c.restoreFlag != 0 && !TextUtils.isEmpty(targetPkg)) {tempPackageKey.update(targetPkg, c.user);SessionInfo si = installingPkgs.get(tempPackageKey);if (si == null) {info.runtimeStatusFlags &=~ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;} else if (activityInfo == null) {int installProgress = (int) (si.getProgress() * 100);info.setProgressLevel(installProgress,PackageInstallInfo.STATUS_INSTALLING);}}// 3.将数据添加到mBgDataModelc.checkAndAddItem(info, mBgDataModel, logger);} else {throw new RuntimeException("Unexpected null WorkspaceItemInfo");}break;case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:FolderInfo folderInfo = mBgDataModel.findOrMakeFolder(c.id);c.applyCommonProperties(folderInfo);// Do not trim the folder label, as is was set by the user.folderInfo.title = c.getString(c.titleIndex);folderInfo.spanX = 1;folderInfo.spanY = 1;folderInfo.options = c.getInt(optionsIndex);// no special handling required for restored foldersc.markRestored();c.checkAndAddItem(folderInfo, mBgDataModel, logger);break;}} catch (Exception e) {Log.e(TAG, "Desktop items loading interrupted", e);}}} finally {IOUtils.closeSilently(c);}// Load delegate itemsmModelDelegate.loadItems(mUserManagerState, shortcutKeyToPinnedShortcuts);// Load string cachemModelDelegate.loadStringCache(mBgDataModel.stringCache);// Remove dead itemsmItemsDeleted = c.commitDeleted();// Sort the folder items, update ranks, and make sure all preview items are high res.FolderGridOrganizer verifier =new FolderGridOrganizer(mApp.getInvariantDeviceProfile());for (FolderInfo folder : mBgDataModel.folders) {Collections.sort(folder.contents, Folder.ITEM_POS_COMPARATOR);verifier.setFolderInfo(folder);int size = folder.contents.size();// Update ranks here to ensure there are no gaps caused by removed folder items.// Ranks are the source of truth for folder items, so cellX and cellY can be ignored// for now. Database will be updated once user manually modifies folder.for (int rank = 0; rank < size; ++rank) {WorkspaceItemInfo info = folder.contents.get(rank);info.rank = rank;if (info.usingLowResIcon()&& info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION&& verifier.isItemInPreview(info.rank)) {mIconCache.getTitleAndIcon(info, false);}}}c.commitRestoredItems();}
}
可以结合db数据进行分析:
- container: 表示显示的布局,像普通、文件夹、dock栏等
- screen: 表示现在第几屏
- itemType:表示类型,像应用图标、文件夹、快捷方式等
图标显示
到这里,我们已经获取到桌面数据了,下面就是要设置到view显示出来。在上面LoaderTask#run()中,loadWorkspace()获取到了数据,而ui显示的触发在mResults.bindWorkspace(true)
bindWorkspace()先是将数据复制一份,然后遍历callback进行bind。上一步mBgDataModel保存了数据库中数据,mBgDataModel是LauncherModel的一个成员变量,在activity#onCreate时创建的,而activity就是Callbacks,所以到这里都关联了起来。
Launcher (Callbacks)—> LoaderTask —> LoaderResults --> BgDataModel --> Callbacks
// LoaderResults.java
/*** Binds all loaded data to actual views on the main thread.*/
public void bindWorkspace(boolean incrementBindId) {// Save a copy of all the bg-thread collectionsArrayList<ItemInfo> workspaceItems = new ArrayList<>();ArrayList<LauncherAppWidgetInfo> appWidgets = new ArrayList<>();final IntArray orderedScreenIds = new IntArray();ArrayList<FixedContainerItems> extraItems = new ArrayList<>();synchronized (mBgDataModel) {workspaceItems.addAll(mBgDataModel.workspaceItems);appWidgets.addAll(mBgDataModel.appWidgets);orderedScreenIds.addAll(mBgDataModel.collectWorkspaceScreens());mBgDataModel.extraItems.forEach(extraItems::add);if (incrementBindId) {mBgDataModel.lastBindId++;}mMyBindingId = mBgDataModel.lastBindId;}for (Callbacks cb : mCallbacksList) {new WorkspaceBinder(cb, mUiExecutor, mApp, mBgDataModel, mMyBindingId,workspaceItems, appWidgets, extraItems, orderedScreenIds).bind();}
}
WorkspaceBinder中bind方法会执行callback回调,回调到activity后,创建BubbleTextView添加到CellLayout。
相关文章:
Launcher3主页面加载显示流程分析
布局结构 抓取布局后,可以看到每个图标是一个DoubleShadowBubbleTextView,父布局是CellLayout、workspace。 我们可以在CellLayout添加子view打印出调用堆栈信息,可以整体上看页面加载显示流程。 主要类 Launcher.java:主界面&…...
机器学习算法---贝叶斯学习
1.了解相关概念 先验概率:有数据集d,以及假设h,此时h是不确定的。在还没有训练数据之前h的初始概率记为P(h),类似地我们把P(d)表示训练数据d在任何假设都未知或不确定时的概率。P(d|h)表示已知假设h成立时d的概率。 后验概率:就是在数据d上经过学习之后…...
PyCharm+RobotFramework框架实现UDS自动化测试——(二)RobotFramework环境配置
从0开始学习CANoe使用 从0开始学习车载测试 相信时间的力量 星光不负赶路者,时光不负有心人。 文章目录 1.环境准配2.Pycharm中相关配置2.1. 安装Hyper RobotFramework Support 3.脚本执行环境3.1 执行单条的配置3.2 执行全部用例配置 4.工程运行4.1 单条用例运行4.…...
colnames看似简单,却能优化数据处理流程
引言 在数据处理和分析中,变量名称是至关重要的,它们决定了数据的可读性和操作的简便性。在R语言中,colnames 函数以其简单的语法设计,提供了高效管理数据框列名的能力,尤其是在复杂的爬虫任务中显得尤为重要。本篇文…...
Spring Boot整合Minio实现文件上传
Spring Boot整合Minio后,前端的文件上传有两种方式: 文件上传到后端,由后端保存到Minio 这种方式好处是完全由后端集中管理,可以很好的做到、身份验证、权限控制、文件与处理等,并且可以做一些额外的业务逻辑…...
GitHub - riscv-software-src/riscv-isa-sim: Spike, a RISC-V ISA Simulator
GitHub - riscv-software-src/riscv-isa-sim: Spike, a RISC-V ISA Simulator 操作手册 $ apt-get install device-tree-compiler libboost-regex-dev libboost-system-dev $ mkdir build $ cd build $ ../configure --prefix$RISCV $ make $ [sudo] make install 具体安装 …...
ceph文件系统
ceph文件系统: 使用设备:4台机器 高度可扩展,分布式的存储文件系统,旨在提供高性能,高可靠性和高可用的对象存储,块存储,文件系统的存储 使用分布式的算法保证数据的高可用和一致性 ceph的架…...
模型创新、论文复现、科研辅导、论文代码定制
建模先锋团队长期致力于为用户提供优质的代码定制服务。团队提供全网最低价格的服务,同时保证高性价比和高质量的代码交付,为您提供个性化定制的服务。 以下是定制服务范围: 通过深度学习和信号处理技术,我们能够针对不同行业和场…...
【flink-cdc】flink-cdc 3版本debug启动pipeline任务,mysql-doris
官方文档 github仓库地址 Flink cdc debug调试动态变更表结构 经过测试使用,在启动任务配置Modify classpath添加jar的方式,容易出错classNotFoundException等等。 一、build project flink-cdc版本:3.2.1 mvn clean package "-Dma…...
mybatisX插件的使用,以及打包成配置
装mybatisX插件; idea连接数据库; 点击mybatisx-generator,设置自己装mybatisX插件; idea连接数据库; 点击mybatisx-generator,设置自己要的包和类; 如果要把自己的配置设置成一个自定义模板&a…...
pip下载包出现SSLError
报错: ERROR: Could not install packages due to an OSError: HTTPSConnectionPool(host‘files.pythonhosted.org’, port443): Max retries exceeded with url: /packages/8a/c2/ae7227e4b089c6a8210920db9d5ac59186b0a84eb1e6d96b9218916cdaf1/taming_transform…...
Linux下查看文件和文件夹占用空间大小
使用Linux命令,查看文件磁盘所占的空间大小,下面可以通过以下命令进行操作 df 可以查看一级文件夹大小、使用比例、档案系统及其挂入点,但对文件束手无策du 查看文件和文件夹的磁盘使用空间 在使用中,一般是df命令和du命令一起联…...
【论文+源码】基于Spring和Spring MVC的汉服文化宣传网站
为了实现一个基于Spring和Spring MVC的汉服文化宣传网站,我们需要创建一个简单的Web应用程序来展示汉服文化和相关信息。这个系统将包括以下几个部分: 数据库表设计:定义文章、用户和评论的相关表。实体类:表示数据库中的数据。DAO层接口及MyBatis映射文件:用于与数据库交…...
C++语言的学习路线
C语言的学习路线 C是一门复杂而强大的编程语言,由于其高性能和灵活性,受到了许多开发者和企业的青睐。无论是系统软件、嵌入式系统还是游戏开发,C都有非常广泛的应用。要掌握C这门语言,需要合理制定学习路线,并结合实…...
【OpenCV】使用Python和OpenCV实现火焰检测
1、 项目源码和结构(转) https://github.com/mushfiq1998/fire-detection-python-opencv 2、 运行环境 # 安装playsound:用于播放报警声音 pip install playsound # 安装opencv-python:cv2用于图像和视频处理,特别是…...
【ArcGISPro/GeoScenePro】解决常见的空间参考和投影问题
修复空间参考缺失的图像 数据 https://arcgis.com/sharing/rest/content/items/535efce0e3a04c8790ed7cc7ea96d02d/data 查看属性坐标 查看属性范围 范围值并不是零或接近于零。 这意味着栅格具有范围,因此其已正确进行...
Ruby语言的语法
Ruby语言的语法之美 Ruby是一种动态、开放源代码的编程语言,由日本的松本行弘(Yukihiro Matsumoto)于1995年首次发布。Ruby语言以其简洁、优雅和易于阅读的语法而闻名。它不仅适合初学者,还被广泛应用于Web开发、数据分析和其他领…...
概述(讲讲python基本语法和第三方库)
我是北子,这是我自己写的python教程,主要是记录自己的学习成果方便自己日后复习, 我先学了C/C,所以这套教程中可能会将很多概念和C/C去对比,所以该教程大概不适合零基础的人。 it seems that python nowadays 只在人工…...
程序包org.springframework.boot不存在
springBoot项目启动报错 程序包org.springframework.boot不存在 1、检查依赖 首先检查pom文件判断依赖是否存在 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId><version>2.4.5…...
.NET Core FluentAPI
目录 约定配置 主要规则 两种配置方式 Data Annotation Fluent API Fluent API配置 Fluent API众多方法 选择 约定配置 主要规则 表名采用DbContext中的对应的DbSet的属性名。数据表列的名字采用实体类属性的名字,列的数据类型采用和实体类属性类型最兼容…...
浙江省自然资源厅:基于“浙里办”的自然资源移动政务服务创新实践——“浙里自然资源”
摘 要:本文基于浙江省自然资源移动政务服务的创新实践,设计和实现“浙里自然资源”应用,依托浙江省省域空间治理数字化平台特有的架构基础,在提升功能性和可用性、加强运营力度、丰富服务内容等方面采取了管理举措和技术创新。通…...
【Astro】如何在Astro上借助Cloudflare D1和Drizzle ORM打造全栈应用?一文带你搞定!
如何在Astro上借助Cloudflare D1和Drizzle ORM打造全栈应用?一文带你搞定! 文章目录 如何在Astro上借助Cloudflare D1和Drizzle ORM打造全栈应用?一文带你搞定!前言一、Astro简介与优势二、Cloudflare D1简介三、Drizzle ORM简介四…...
【Axios使用手册】如何使用axios向后端发送请求并进行数据交互
axios 是一个基于 Promise 的 HTTP 客户端,用于浏览器和 Node.js。它支持请求和响应拦截、取消请求、自动转换 JSON 数据等功能,非常适合在现代 JavaScript 应用中进行网络请求。以下是对 axios 的详细讲解,包括安装、基本用法、高级功能等。…...
边缘计算应用十大领域
边缘计算解决了互联网的网速问题,作为实现边缘计算的基础,那边缘计算是5G与产业互联网、物联网时代的重要技术支撑,也正迎来广阔的增长空间。那么现在我们生活中有哪些领域正在使用边缘计算呢?今天我们来盘点一下我们身边正在使用…...
CSS 学习之 padding 与图形绘制
padding 属性和 background-clip 属性配合,可以在有限的标签下实现一些 CSS 图形绘制效果,我这里举两个小例子,重在展示可行性。 例 1:不使用伪元素,仅一层标签实现大队长的“三道杠”分类图标效果。此效果在移动端比较常见&…...
熔断器模式如何进入半开状态的
熔断器模式在进入打开状态并经过一段冷却时间后,会自动进入半开状态。这个过程是熔断器模式自我恢复机制的一部分,旨在测试下游服务是否已经恢复正常,从而决定是否重新允许请求通过。 1. 进入打开状态: • 当服务调用失败次数达到…...
数据结构:双向循环链表
双向循环链表(Doubly Circular Linked List) 双向循环链表是双向链表的一种变体,其特点是链表的头节点和尾节点相连,形成一个闭环。这种结构允许在链表中进行无缝的双向遍历,并且由于循环特性,可以从任何节…...
宝安湾区之光附近的钓鱼点
工作日的午休我经常在公司附近骑行,有时候也会骑行到宝安的湾区之光。但是我最感兴趣的除了湾区之光摩天轮,还有雷打不动的快乐钓鱼佬。 上图红框区域的河岸每天都会出现零零散散的快乐钓鱼佬,他们好像都有自己的钓鱼窝点。我发现来这里钓鱼也…...
【计算机网络】什么是AC和AP?
在现代的无线网络中,AC(Access Controller,接入控制器)和AP(Access Point,无线接入点)是两个至关重要的设备,它们在网络的管理、连接和优化中扮演着重要角色。理解它们的功能和区别&…...
python 词法分析
词法分析(Lexical Analysis)是编译器的第一步,它的任务是将源代码文本分割成一系列有意义的单元(称为“词法单元”或“Token”)。这些词法单元通常包括关键字、标识符、常量、运算符、分隔符等。 import re# 定义词法单…...
JUC--CAS原理(以Atomic报下类的实现来了解CAS的原理)
以Atomic来了解CAS的原理 六、无锁6.1CAS(Compare-And-Swap)原理6.2CAS与synchronized6.3Atomic(原子类)原理分析 6.4ABA问题6.4unsafe 六、无锁 6.1CAS(Compare-And-Swap)原理 CAS原理:CAS是…...
对比显式启用-u_printf_float和-u_scanf_float前后的代码内存体量实验
本文的嵌入式编译器基于GCC for ARM,构建文件基于Makefile。 main.c不编写任何代码,保证实验的其他变量统一。源文件main.c: 优化等级固定为 -Og : syscalls.c 系统调用库函数文件参考:基于GCC for ARM交叉编译工具链…...
嵌入式 Linux LED 驱动开发实验
一、Linux 下 LED 灯驱动原理 a)地址映射 在编写驱动之前,我们需要先简单了解一下 MMU 这个神器, MMU 全称叫做 Memory Manage Unit,也就是内存管理单元。在老版本的 Linux 中要求处理器必须有 MMU,但是现在 Linux 内核已经支持无 MMU 的处理器了。 MMU 主要完成的功能如…...
qml PathView详解
1、概述 PathView 是 Qt Quick 中一个非常强大的视图组件,它基于一个 Path 来展示视图项(如 Item、Rectangle 等)。PathView 可以让你按照定义的路径动态地显示多个元素,并且支持动画、滑动等功能。这个视图控件的最大特点是能够…...
Spring源码分析之事件机制——观察者模式(一)
目录 事件基类定义 事件监听器接口 事件发布者接口及实现 事件广播器实现 小小总结 Spring源码分析之事件机制——观察者模式(一)-CSDN博客 Spring源码分析之事件机制——观察者模式(二)-CSDN博客 Spring源码分析之事件机制…...
安卓14无法安装应用解决历程
客户手机基本情况: 安卓14,对应的 targetSdkVersion 34 前天遇到了安卓14适配问题,客户发来的截图是这样的 描述:无法安装我们公司的B应用。 型号:三星google美版 解决步骤: 1、寻找其他安卓14手机测试…...
BGP(Border Gateway Protocol)路由收集器
全球 BGP(边界网关协议)路由收集器的分布情况以及相关数据。以下是主要的信息解读: 地图标记: 每个绿色点代表一个路由收集器的位置。路由收集器分布在全球不同的地区,覆盖了五大区域: ARIN(美…...
Vue.js与其他框架有哪些兼容性?
Vue.js的兼容性主要体现在几个方面,包括浏览器支持、运行环境适应性、与其他库和框架的集成能力等。以下是更详细的解释: 浏览器兼容性 现代浏览器:Vue.js广泛支持所有主流的现代浏览器,如Google Chrome, Firefox, Safari, Edge…...
深度解析与实践:HTTP 协议
一、引言 HTTP(HyperText Transfer Protocol,超文本传输协议)是 Web 应用程序、API、微服务以及几乎所有互联网通信的核心协议。虽然它是我们日常使用的基础技术,但要深刻理解其高效使用、优化以及如何避免性能瓶颈,我…...
MyBatis 配置文件全解析
一、MyBatis 配置文件为何至关重要? 在 Java 后端开发领域,MyBatis 作为一款广受欢迎的持久层框架,极大地简化了数据库操作。而 MyBatis 配置文件,恰似整个框架的 “神经中枢”,掌控着其运行的方方面面,对…...
redis Redis内存缓存过期机制
起因:随着项目的进一步推广,数据量的增大,直接访问mysql数据库获取数据所使用的时间越来越长,为解决当前主要矛盾,决定引入redis非关系型数据库作为缓存层,使得数据并不能直接命中数据库,减少访…...
游戏关卡设计的常用模式
游戏关卡分为很多种,但常用的有固定套路,分为若干种类型。 关卡是主角与怪物、敌方战斗的场所,包括装饰物、通道。 单人游戏的关卡较小,偏线性; 联机/MMO的关卡较大,通道多,自由度高…...
计算机网络常见面试题及解答
以下是计算机网络中常见的面试题及解答,按主题分类: --- ## **一、基础概念** ### **1. OSI 七层模型和 TCP/IP 模型的区别是什么?** **答:** - **OSI 七层模型:** - 应用层、表示层、会话层、传输层、网络层、数…...
SUB输入5V升压充电16.8V芯片HU5912
HU5912芯片,作为航誉微电子有限公司推出的一款高性能升压充电管理IC,自其面世以来,便以其出色的性能和广泛的应用领域,受到了业界的高度关注和赞誉。本文将详细介绍HU5912芯片的技术特点、应用优势、市场定位以及其在各类电子设备…...
基于Informer网络实现电力负荷时序预测——cross validation交叉验证与Hyperopt超参数调优
前言 系列专栏:【深度学习:算法项目实战】✨︎ 涉及医疗健康、财经金融、商业零售、食品饮料、运动健身、交通运输、环境科学、社交媒体以及文本和图像处理等诸多领域,讨论了各种复杂的深度神经网络思想,如卷积神经网络、循环神经网络、生成对…...
linux ubantu重启桌面
在 Ubuntu 系统中,重启桌面环境通常有几种方法,具体取决于你所使用的桌面环境(如 GNOME、KDE 等)。下面是几种常用的重启桌面的方法: 重启 GNOME 桌面环境 如果你使用的是 GNOME 桌面环境(Ubuntu 默认桌面…...
C++Primer const限定符
欢迎阅读我的 【CPrimer】专栏 专栏简介:本专栏主要面向C初学者,解释C的一些基本概念和基础语言特性,涉及C标准库的用法,面向对象特性,泛型特性高级用法。通过使用标准库中定义的抽象设施,使你更加适应高级…...
【机器学习】机器学习的基本分类-自监督学习(Self-supervised Learning)
自监督学习是一种机器学习方法,介于监督学习和无监督学习之间。它通过数据本身生成标签,创建训练任务,从而学习数据的表征,而不需要人工标注的标签。这种方法在减少标注数据依赖、提高模型通用性等方面具有重要意义。 自监督学习的…...
python基础案例
#一个年份如果能被4整除但不能被 100整除,或能被 400整除,那么这个年份就是闰年。 year int(input(请输入年份:)) if (year %40 and year %100!0) or year %4000:print("这个年份就是闰年") else:print("这个年份不是闰…...
ARP(地址解析协议)攻击;TCP SYN Flood(SYN洪流)攻击
ARP(地址解析协议)攻击 是一种网络攻击类型,攻击者利用ARP协议的缺陷对目标网络实施攻击。ARP协议用于在局域网(LAN)中将IP地址解析为MAC地址,它是无认证机制的,这为攻击者提供了可利用的机会。…...