当前位置: 首页 > news >正文

HarmonyOS实战开发-一次开发,多端部署-视频应用

介绍

随着智能设备类型的不断丰富,用户可以在不同的设备上享受同样的服务,但由于设备形态不尽相同,开发者往往需要针对具体设备修改或重构代码,以实现功能完整性和界面美观性的统一。OpenHarmony为开发者提供了“一次开发,多端部署”的系统能力,让开发者可以基于一次开发,快速构建不同类型终端上的应用,降低开发成本,提高开发效率。

本篇Codelab基于“一次开发,多端部署”提供的自适应布局和响应式布局能力,实现了常见的视频播放应用的主界面。通过三层工程结构尽可能复用了部分代码,并根据设备尺寸的区别设计了对应的页面以兼顾美观和易用。应用被打开时会根据具体的设备形态显示对应的UI界面,其中RK3568开发板的首页效果如图所示:

相关概念

  • 一次开发,多端部署:指一套代码工程,一次开发上架,多端按需部署,目标是支撑开发者高效地开发支持多种终端设备形态的应用。
  • 自适应布局:当外部容器大小发生变化时,元素可以根据相对关系自动变化以适应外部容器变化的布局能力。相对关系如占比、固定宽高比、显示优先级等。当前自适应布局能力有7种:拉伸能力、均分能力、占比能力、缩放能力、延伸能力、隐藏能力、折行能力。自适应布局能力可以实现界面显示随外部容器大小连续变化。
  • 响应式布局:当外部容器大小发生变化时,元素可以根据断点、栅格或特定的特征(如屏幕方向、窗口宽高等)自动变化以适应外部容器变化的布局能力。当前响应式布局能力有3种:断点、媒体查询、栅格布局。
  • GridRow:栅格容器组件,仅可以和栅格子组件(GridCol)在栅格布局场景中使用。
  • GridCol:栅格子组件,必须作为栅格容器组件(GridRow)的子组件使用。

环境搭建

软件要求

  • DevEco Studio版本:DevEco Studio 3.1 Release。
  • OpenHarmony SDK版本:API version 9。

硬件要求

  • 开发板类型:润和RK3568开发板。
  • OpenHarmony系统:3.2 Release。

环境搭建

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. 获取OpenHarmony系统版本:标准系统解决方案(二进制)。以3.2 Release版本为例:

2.搭建烧录环境。

  1. 完成DevEco Device Tool的安装
  2. 完成RK3568开发板的烧录

3.搭建开发环境。

  1. 开始前请参考工具准备,完成DevEco Studio的安装和开发环境配置。
  2. 开发环境配置完成后,请参考使用工程向导创建工程(模板选择“Empty Ability”)。
  3. 工程创建完成后,选择使用真机进行调测。

代码结构解读

本篇Codelab只对核心代码进行讲解,对于完整代码,我们会在gitee中提供。

“一次开发,多端部署”推荐使用三层目录的工程结构来管理工程,上层目录包括common、features和product,common为公共特性目录,存放不同形态设备公用的类和常量,features为功能模块目录,存放应用的各个功能模块,product为产品层目录,存放不同形态设备范类代码。本Codelab不涉及功能特性,因此只存在common、product两个分层。

├──common                                // 公共能力层
│  ├──src/main/ets
│  │  ├──constants
│  │  │  └──CommonConstants.ets          // 公共常量类
│  │  ├──utils
│  │  │  └──BreakpointSystem.ets         // 断点工具类
│  │  └──viewmodel                       // 资源类接口
│  │     ├──BottomTabsItem.ets
│  │     ├──DriveTabsItem.ets  
│  │     ├──FindTabsItem.ets
│  │     ├──HomeTabsItem.ets
│  │     └──MineTabsItem.ets
│  └──src/main/resources                 // 资源文件夹
└──product                               // 产品定制层├──default/src/main/ets               // 支持手机(含折叠屏)、平板│  ├──entryability│  │  └──EntryAbility.ts              // 程序入口类│  ├──pages│  │  └──MainPage.ets                 // 主页面│  ├──view│  │  ├──BottomTabsComponent.ets      // 底部页签组件│  │  ├──DriveTabsComponent.ets       // 云盘页组件│  │  ├──FindTabsComponent.ets        // 发现页组件│  │  ├──HomeTabsComponent.ets        // 首页组件│  │  ├──LeftTabsComponent.ets        // 侧边栏组件│  │  ├──MineTabsComponent.ets        // 个人页组件│  │  ├──RecentlyPlayedComponent.ets  // “最近播放”列表│  │  └──RecommendComponent.ets       // “为你推荐”列表│  └──viewmodel│     ├──BottomTabsModel.ets          // 底部页签model│     ├──DriveTabsModel.ets           // 云盘页model│     ├──FindTabsModel.ets            // 发现页model│     ├──HomeTabsModel.ets            // 首页model│     └──MineTabsModel.ets            // 个人页model└──default/src/main/resources         // 资源文件夹

主页面框架设计

为了操作便捷和充分利用不同形态设备的屏幕空间,按屏幕宽度的大小将设备划分为3类:

  • sm:320vp<=width<520vp,典型设备为手机。
  • md:520vp<=width<840vp,典型设备为折叠屏。
  • lg:840vp<=width,典型设备为平板或PC。

根据用户使用场景,当操作设备尺寸为sm或md时,一般为竖向使用,此时用于切换应用页面的页签栏适合置于底部。当操作设备尺寸为lg时,一般为横向使用,此时页签栏适合置于左侧。

// MainPage.ets
@Entry
@Component
struct MainPage {...build() {SideBarContainer(SideBarContainerType.Embed) {LeftTabs({ bottomTabIndex: $bottomTabIndex });  // 侧边栏Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.End, justifyContent: FlexAlign.End }) {Tabs({ barPosition: BarPosition.End, index: 0, controller: this.controller }) {... // 页面内容}if (this.currentBreakpoint !== Const.LG) {BottomTabs({ bottomTabIndex: $bottomTabIndex })  // 底部栏,当屏幕尺寸不为"lg"时显示}}.width(Const.FULL_SIZE).backgroundColor($r('app.color.background_color'))}.showSideBar(this.currentBreakpoint === Const.LG)  // 当屏幕尺寸为"lg"时显示侧边栏.showControlButton(false).sideBarWidth(Const.SIDEBAR_WIDTH).maxSideBarWidth(Const.SIDEBAR_WIDTH_MAX).minSideBarWidth(Const.SIDEBAR_WIDTH_MIN)}
}

各页面代码实现

首页

首页显示轮播图和“最近播放”、“为你推荐”两个列表,轮播图根据屏幕尺寸的区别,有显示数量的不同(sm为1,md为2,lg为3),列表使用具备自适应布局能力的List组件。

// HomeTabsComponent.ets
@Component
export struct HomeTabs {@Link currentBreakpoint: string;private scroller: Scroller = new Scroller();build() {Scroll(this.scroller) {GridRow({// 设置sm、md和lg的布局列数分别为4、8、12columns: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_8, lg: Const.GRID_12 },gutter: { x: $r('app.float.gutter_home') },breakpoints: { value: [Const.BREAKPOINTS_SM, Const.BREAKPOINTS_MD, Const.BREAKPOINTS_LG] }}) {GridCol({ span: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_8, lg: Const.GRID_12 } }) {... // 标题}.height($r('app.float.title_height')).margin({ bottom: $r('app.float.home_margin1') })// 搜索栏在sm、md下占满全部列,在lg下占8列GridCol({ span: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_8, lg: Const.GRID_8 } }) {... // 搜索栏}.height($r('app.float.home_grid_height1'))GridCol({ span: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_8, lg: Const.GRID_12 } }) {Swiper() {...}.height($r('app.float.home_swiper_height')).itemSpace(Const.ITEM_SPACE)// 根据屏幕尺寸大小选择不同的轮播图数量.displayCount(this.currentBreakpoint === Const.LG ?Const.NUM_3 : (this.currentBreakpoint === Const.MD ? Const.NUM_2 : Const.NUM_1))}.height($r('app.float.home_grid_height2'))GridCol({ span: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_8, lg: Const.GRID_12 } }) {... // ”最近播放”列表}.height($r('app.float.home_grid_height3'))GridCol({ span: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_8, lg: Const.GRID_12 } }) {... // ”为你推荐”列表 }.height($r('app.float.home_column_height'))}.height(Const.FULL_SIZE)}...}
}

发现页

发现页使用栅格布局实现“一次开发,多端部署”能力,把sm设置为4列,md设置为8列,lg设置为12列。热播榜单在不同设备尺寸上分别占据4列、6列和8列。

// FindTabsComponent.ets
@Component
export struct FindTabs {private scroller: Scroller = new Scroller();build() {Scroll(this.scroller) {GridRow({// 设置sm、md和lg的布局列数分别为4、8、12columns: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_8, lg: Const.GRID_12 },gutter: { x: $r('app.float.gutter_find') },breakpoints: { value: [Const.BREAKPOINTS_SM, Const.BREAKPOINTS_MD, Const.BREAKPOINTS_LG] }}) {GridCol({ span: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_8, lg: Const.GRID_12 } }) {... // 标题}.height($r('app.float.title_height'))LazyForEach(new FindDataSource(FindTabsList), (item: FindTabsItem) => {// 设置热播榜单在sm、md和lg上分别占据4、6、8列,并且设置offset属性保证在不同设备形态上都能保持居中GridCol({span: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_6, lg: Const.GRID_8 },offset: {md: FindTabsList.indexOf(item) === Const.OFFSET_0 ? Const.OFFSET_1 : Const.OFFSET_2,lg: FindTabsList.indexOf(item) === Const.OFFSET_0 ? Const.OFFSET_2 : Const.OFFSET_4}}) {... // 榜单内容}}, (item: FindTabsItem) => JSON.stringify(item))}}...}
}

RK3568开发板上发现页的实际效果如图所示:

云盘页

云盘页的栅格划分和发现页相同,但是每个子组件在所有屏幕尺寸上都只占据2列。

// DriveTabsComponent.ets
@Component
export struct DriveTabs {private scroller: Scroller = new Scroller();build() {Scroll(this.scroller) {GridRow({// 设置sm、md和lg的布局列数分别为4、8、12columns: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_8, lg: Const.GRID_12 },gutter: { x : $r('app.float.gutter_drive') },breakpoints: { value: [Const.BREAKPOINTS_SM, Const.BREAKPOINTS_MD, Const.BREAKPOINTS_LG] }}) {GridCol({ span: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_8, lg: Const.GRID_12 } }) {... // 标题}.height($r('app.float.title_height'))ForEach(DriveList, (item: DriveTabsItem) => {// 设置云盘内容在sm、md和lg上均占据2列GridCol({ span: { xs: Const.NUM_2, sm: Const.NUM_2, md: Const.NUM_2, lg: Const.NUM_2 } }) {... // 云盘内容}}, (item: DriveTabsItem) => JSON.stringify(item))}}...}
}

RK3568开发板上云盘页的实际效果如图所示:

个人页

个人页的栅格划分仍然和发现页相同,但子组件在sm、md形态下占满全部列,在lg形态下只占据8列。

// MineTabsComponent.ets
@Component
export struct MineTabs {private scroller: Scroller = new Scroller();build() {Scroll(this.scroller) {GridRow({// 设置sm、md和lg的布局列数分别为4、8、12columns: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_8, lg: Const.GRID_12 },gutter: { x: $r('app.float.gutter_mine') },breakpoints: { value: [Const.BREAKPOINTS_SM, Const.BREAKPOINTS_MD, Const.BREAKPOINTS_LG] }}) {// 设置个人页在sm和md上占满全部列,在lg上占8列,为保证居中在lg上设置offset为2列GridCol({span: { xs: Const.GRID_4, sm: Const.GRID_4, md: Const.GRID_8, lg: Const.GRID_8 },offset: { lg: Const.OFFSET_2 }}) {... // 个人页内容}}.height(Const.FULL_SIZE).backgroundColor($r('app.color.mine_background_color'))}...}
}

RK3568开发板上个人页的实际效果如图所示:

总结

您已经完成了本次Codelab的学习,并了解到以下知识点:

  1. 根据设备尺寸形态设计不同的页面布局。
  2. 使用栅格布局实现“一次开发,多端部署”能力。

为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了一份全套最新版的HarmonyOS NEXT学习资源,获取完整版方式请点击→《HarmonyOS教学视频

HarmonyOS教学视频:语法ArkTS、TypeScript、ArkUI等.....视频教程

鸿蒙生态应用开发白皮书V2.0PDF:

获取完整版白皮书方式请点击→《鸿蒙生态应用开发白皮书V2.0PDF》

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

  1. 应用开发导读(ArkTS)
  2. ……

二、HarmonyOS 概念

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全
  5. ........

三、如何快速入门?《做鸿蒙应用开发到底学习些啥?》

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. ……

四、开发基础知识

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. ……

五、基于ArkTS 开发

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. ……

更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册》

相关文章:

HarmonyOS实战开发-一次开发,多端部署-视频应用

介绍 随着智能设备类型的不断丰富&#xff0c;用户可以在不同的设备上享受同样的服务&#xff0c;但由于设备形态不尽相同&#xff0c;开发者往往需要针对具体设备修改或重构代码&#xff0c;以实现功能完整性和界面美观性的统一。OpenHarmony为开发者提供了“一次开发&#x…...

关于v114之后的chromedriver及存放路径

使用selenium调用浏览器时&#xff0c;我一直调用谷歌浏览器&#xff0c;可浏览器升级后&#xff0c;就会再次遇到以前遇到过的各种问题&#xff0c;诸如&#xff1a;1、怎么关闭浏览器更新&#xff1b;2、去哪儿下载chromedriver&#xff1b;3、114版本之后的驱动去哪儿下载&a…...

http模块 服务器端如何响应(获取)静态资源?

一、静态资源与动态资源介绍&#xff1a; &#xff08;1&#xff09;静态资源 内容长时间不改变的资源。eg&#xff1a;图片、视频、css js html文件、字体文件... &#xff08;2&#xff09;动态资源 内容经常更新的资源。eg&#xff1a;百度首页、淘宝搜索列表... 二、服…...

基于PHP的校园招聘管理系统

有需要请加文章底部Q哦 可远程调试 基于PHP的校园招聘管理系统 一 介绍 此校园招聘管理系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端bootstrap。系统角色分为个人用户&#xff0c;企业和管理员三种。 技术栈&#xff1a;phpmysqlbootstrapphpstudyvscode 二…...

LLMs 可能在 2 年内彻底改变金融行业

在艾伦图灵研究所&#xff08;The Alan Turing Institute&#xff09;最新的一项研究中&#xff0c;我们看到了大型语言模型&#xff08;Large Language Models&#xff0c;LLMs&#xff09;的一种可能性。它有望通过检测欺诈行为、生成财务洞察以及自动化客户服务&#xff0c;…...

nodejs 中 yarn的安装和使用

Yarn是一个快速、可靠、易于使用的包管理工具,它是Facebook、Google、Tencent等公司使用的默认JavaScript包管理工具。Yarn可以帮助开发者在项目中管理依赖,确保不同环境之间的依赖一致性,并且加速依赖的下载和安装。 安装Yarn Yarn支持多种操作系统,包括macOS、Linux和W…...

软件工程学习笔记14——案例解析篇

案例解析篇 一、大型开源项目对软件工程的应用1、开发迭代过程 二、大厂是怎样应用软件工程的1、软件项目开发团队组成&#xff08;1&#xff09;软件开发团队规模小&#xff08;2&#xff09;没有专职测试&#xff08;3&#xff09;DevOps 文化 2、开发工具的使用3、项目开发流…...

【文件操作API的使用】

1.概念 这对聪明的你们来说简直就是&#xff0c;对吗。 那什么是文件操作符&#xff0c;文件操作又有哪些步骤呢&#xff1f; 文件操作符通常用于指代在计算机编程中用于处理文件的特殊符号或标识符。在很多编程语言中&#xff0c;文件操作符被用于打开、关闭、读取和写入文件…...

C++ 让类只在堆或栈上分配

1. 让类只在栈上或堆上分配内存 在C中&#xff0c;类的对象建立分为两种&#xff1a; 一种是静态建立&#xff0c;如A a&#xff1b; 另一种是动态建立&#xff0c;如A* ptrnew A&#xff1b;这两种方式是有区别的。 1、静态建立类对象&#xff1a;是由编译器为对象在栈空间…...

SpringMVC源码分析(九)--返回值解析器

1.返回值解析器介绍 返回值解析器用于解析Hanlder执行方法后的返回结果,例如将方法上标注有@ResponseBody注解的返回值解析成JSON、将方法返回的字符串作为视图名等 SpringMVC中默认的返回值解析器见RequestMappingHandlerAdapter#getDefaultReturnValueHandlers private L…...

京西商城——创建订单和获取订单接口

在之前的写过的接口中&#xff0c;我先后用了基于View和APIView来编写视图类 基于APIView类的时候相对于View会有很多便捷&#xff0c;但其实drf还在APIView的基础上又封装了一个 GenericAPIView 类&#xff0c;会大大减少了在编写视图时的重复代码和在修改代码时的工作量。 G…...

大话设计模式之模板方法模式

模板方法模式&#xff08;Template Method Pattern&#xff09;是一种行为设计模式&#xff0c;它定义了一个算法的框架&#xff0c;将特定步骤的实现延迟到子类中。模板方法模式通过在父类中定义算法的骨架&#xff0c;而将具体步骤的实现留给子类来完成&#xff0c;从而使子类…...

新model开发记录

模型使用 -- 用blender导出为 fbx &#xff0c;修改渲染方式&#xff08;点击模型->Materials->Extract Materials(将材质从fbx中 单独提取出来了)->Materials 选择 Shader -> SimpleURPToonLitExample 点开脸的材质&#xff0c;勾选第一条&#xff09; 解决角色…...

ARMday1

1.总结keil5下载代码和编译代码需要注意的事项 答&#xff1a;下载代码时&#xff0c;确保stlink的驱动有效、魔术棒中硬件型号的连接 编译代码时&#xff0c;先将配置魔术棒里Debug中的Setting&#xff0c;将Flash中Reset and Run勾选上&#xff0c;并去除pack中的Enab…...

【C++风云录】创造视觉奇迹:探索C++图形编程的魅力与可能性

图形与界面&#xff1a;从SFML到Allegro&#xff0c;探索C图形编程的世界 前言 随着计算机图形技术和界面设计的快速发展&#xff0c;图形编程在软件开发中变得越来越重要。C作为一种功能强大的编程语言&#xff0c;为开发人员提供了丰富的图形编程工具和库。本文将介绍几个流…...

常见的Nginx+Redis+MQ+DB架构设计

三高&#xff0c;复杂的架构 SQRS CAP 缓存&#xff0c;限流 【Redis&#xff0c;缓存】 cache-aside 缓存cache&#xff1a;数据源的副本 store 1. Read/Write Through Pattern 读写穿透模式 redis&#xff1a;放当前在线用户&#xff0c;热点数据...

vue+elementUI搭建动态表头的表格

前提&#xff1a;以下代码是vue2项目结合elementUi完成的 数据结构 后端传来的数据是两个list&#xff0c;一个表头的list&#xff0c;一个表格内容的list // 表头 headTableAtts: [{ columnLabel: 姓名, columnName: name },{ columnLabel: 年龄, columnName: age },{ colu…...

【ENSP】交换机和交换机之间实现静态路由

1.概念 三层交换机只能在Vlanif逻辑口配置iP地址 2.实现方法 交换机允许对应vlan通行&#xff0c;配置vlanif的ip地址&#xff0c;做静态路由 3.静态路由配置方法 ip route-static 目的网段 子网掩码 下一跳设备 LSW1三层交换机配置 u t m sys vlan batch 10 20 …...

2024.2.18力扣每日一题——N叉树的前序遍历

2024.2.18 题目来源我的题解方法一 深度优先遍历&#xff08;递归方式&#xff09;方法二 迭代方式&#xff08;栈实现&#xff09; 题目来源 力扣每日一题&#xff1b;题序&#xff1a;589 我的题解 方法一 深度优先遍历&#xff08;递归方式&#xff09; 与二叉树的前序遍…...

Taro活动列表中,对某一个活动添加分享按钮

采用data-留下分享链接的拼接参数 1.在item文件中写按钮 openType“share” <ButtonclassName{classes.rowRightShareButton}openType"share"data-share-transfer-id{lastGiftingTransferId}data-share-picture-url{shareUrl}data-share-title{shareTitle}onClic…...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

Java入门学习详细版(一)

大家好&#xff0c;Java 学习是一个系统学习的过程&#xff0c;核心原则就是“理论 实践 坚持”&#xff0c;并且需循序渐进&#xff0c;不可过于着急&#xff0c;本篇文章推出的这份详细入门学习资料将带大家从零基础开始&#xff0c;逐步掌握 Java 的核心概念和编程技能。 …...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

ThreadLocal 源码

ThreadLocal 源码 此类提供线程局部变量。这些变量不同于它们的普通对应物&#xff0c;因为每个访问一个线程局部变量的线程&#xff08;通过其 get 或 set 方法&#xff09;都有自己独立初始化的变量副本。ThreadLocal 实例通常是类中的私有静态字段&#xff0c;这些类希望将…...

Xcode 16 集成 cocoapods 报错

基于 Xcode 16 新建工程项目&#xff0c;集成 cocoapods 执行 pod init 报错 ### Error RuntimeError - PBXGroup attempted to initialize an object with unknown ISA PBXFileSystemSynchronizedRootGroup from attributes: {"isa">"PBXFileSystemSynchro…...

Linux操作系统共享Windows操作系统的文件

目录 一、共享文件 二、挂载 一、共享文件 点击虚拟机选项-设置 点击选项&#xff0c;设置文件夹共享为总是启用&#xff0c;点击添加&#xff0c;可添加需要共享的文件夹 查询是否共享成功 ls /mnt/hgfs 如果显示Download&#xff08;这是我共享的文件夹&#xff09;&…...

可下载旧版app屏蔽更新的app市场

软件介绍 手机用久了&#xff0c;app越来越臃肿&#xff0c;老手机卡顿成常态。这里给大家推荐个改善老手机使用体验的方法&#xff0c;还能帮我们卸载不需要的app。 手机现状 如今的app不断更新&#xff0c;看似在优化&#xff0c;实则内存占用越来越大&#xff0c;对手机性…...