面向万物智联的应用框架的思考和探索(上)
原文:面向万物智联的应用框架的思考和探索(上),点击链接查看更多技术内容。
应用框架,是操作系统连接开发者生态,实现用户体验的关键基础设施。其中,开发效率和运行体验是永恒的诉求,业界也在持续不断的发展和演进。
本文重点围绕移动应用框架,梳理其关键发展脉络,并分析其背后的技术演进思路以及目前的局限;同时,进一步结合万物智联的新场景和新生态,围绕相应的应用框架的设计和演进,分享个人在这个领域的思考,实践,以及下一步探索。
“凡是过往,皆为序章”- 威廉 · 莎士比亚
1、应用框架概览
1.1应用,以及应用框架的基本组成
应用是用户使用操作系统/设备的入口,应用框架则是应用开发和运行的基础设施。用户通过各种各样的应用来和操作系统/设备交互,来满足相应的需求。以移动平台为例,一个典型的应用以及相对应的应用框架的基础组成大致如下所示:
Figure 1 典型的应用结构以及相应的系统运行环境
一个典型的应用结构主要包括以下几个部分:
1)用户界面以及相应的业务处理逻辑。这里主要包括构建用户界面所需的UI(User Interface)组件,布局,动效,事件交互响应处理,所需的资源(图片/字体等),以及结合UI呈现的业务逻辑处理等。从运行时的维度来看,它主要对应了系统运行环境中的UI框架(含语言运行时),以及部分的系统能力API (Application Programming Interface);
2)共享库。这里主要包括开发者封装好的SDK(Software Development Kit),以及使用的三方库等。从运行时维度来看,它主要对应了系统能力API以及语言运行时,如果共享库涉及UI的话,还对应了UI框架;
3)包清单文件。这里主要包括应用包的结构描述,权限声明等,它主要对应了系统运行环境中的包管理,应用生命周期/权限管理/进程管理等。
其中, UI框架的主要组成如下图所示:
Figure 2 UI框架的主要组成
开发模型:对开发者提供的开发范式、UI组件/API能力、编程语言等,重点体现的是开发效率与难易程度;
运行框架:UI界面渲染及交互的基础能力框架,将开发者的程序运行在具体系统平台上,包括应用整体渲染处理流程,语言逻辑执行流程,以及平台能力扩展机制,重点体现的是应用运行的性能体验;
平台适配:承载框架的具体操作系统或平台的适配层。
一般而言,应用框架中的包管理、生命周期/权限管理,和具体的操作系统关联较紧,并相对稳定;能力API则是操作系统对设备能力的封装,主要影响应用使用设备的能力。UI框架以及相应的编程语言则是影响用户体验(包括开发和运行体验)的关键要素,尤其随着移动平台的不断普及以及移动设备的差异,移动平台上的UI框架(含编程语言)是业界不断演进的重点领域。
1.2移动平台上应用框架的演进
纵观十年来的发展,总体而言,移动平台上应用框架围绕着原生框架,三方跨平台框架交织发展,并结合相应语言、工具的配套演进。下图描述了其中的关键框架/语言的演进概览。
Figure 3 移动平台上关键语言/开发框架/工具演进概览
图中有几个关键节点:
1) 2013年,Facebook发布的React.js第一次综合的将数据绑定,虚拟DOM(Document Object Model)等机制引入前端开发框架设计中。开发者只需声明好相应的数据和UI的绑定,之后由框架来跟踪数据的变化,并通过虚拟DOM树的对比找出变化点,从而实现界面的自动更新,而无需开发者手动基于DOM 编程。
2)2018年,Google发布的Flutter则是个重要的分界点。Flutter融合了Dart语言,是第一个深度融合了语言的较为完整的声明式开发框架,实现了完全通过数据驱动的UI变更。另外,Flutter通过基于Skia的自绘制引擎实现了高性能的跨平台的平台一致性的渲染能力,并提供了Hot Reload机制提升开发测试体验。不过,Flutter的整体设计哲学偏向底层的灵活性 – 主要通过底层的细粒度的能力供开发者自由组合,另外,Google对Dart语言的简洁度的改进较少,整体上开发的简洁度以及对用户的友好度相对不足。
3)2019年,Apple SwiftUI的推出,意味着主流OS的原生应用框架开始逐步往声明式开发方式迁移。SwiftUI推动了Swift语言特性扩展实现了更加简洁自然的UI描述,并通过XCode开发工具的所见即所得的高效预览能力进一步提升开发效率。同时,SwiftUI也是真正意义上开始通过一套框架,逐步统一Apple生态中的不同的设备/OS上的应用开发。
另外,2019年Google将更简洁的Kotlin语言升级为Android首选的编程语言,并在2021年推出基于Kotlin的UI框架Jetpack Compose, 同时结合开发工具Android Studio逐步往多设备以及跨平台演进。
总体而言,移动端应用框架的演进包含以下几个关键特征:
1)从命令式UI开发逐步演进到声明式UI开发
2)UI和编程语言的融合从相对松散演进到逐步紧密
3)开发范围从单设备演进到多设备,从单平台演进到多平台
接下来的章节会分别围绕跨平台框架,以及原生应用框架逐步展开,梳理其具体的演进脉络。
1.2.1 跨平台框架
由于W3C( World Wide Web Consortium)标准的普及以及Web天然的跨平台能力, 跨平台框架主要是基于Web或Web的衍生技术。
最早试图补齐Web跨平台能力是一家叫做PhoneGap的公司,后面被Adobe收购,2012年以Cordova的项目名开源发布。当时的W3C标准更多涵盖的是页面渲染,而设备相关能力的标准非常缺失,PhoneGap的目标则是围绕着“Phone”补齐这方面能力“Gap” – 它定义了一套移动平台上常用的设备能力的JS API,并基于JS引擎设计了一套扩展方式来实现不同平台上的API,同时结合系统的Webview,配套相关系统整合以及打包工具,部署成相应平台上的应用格式在目标操作系统平台上运行。PhoneGap一定程度上促进了Web在移动设备上的发展,但是它没有解决Web引擎本身的体验问题。当时的Web引擎(系统自带的Webview),尤其是Android平台上,能力较弱,并缺失硬件加速,稍微复杂的应用体验较差。针对这些问题,2014年 Intel开源技术中心推出了Crosswalk项目,在Chromium内核基础上,针对移动平台上Web应用,做了进一步解耦和性能优化(包括硬件加速,包体积优化,以及针对游戏专门设计一套渲染路径等),并结合了Cordova补齐相关API能力,构建了可独立打包演进的Web引擎,性能体验得到了较大的提升。而且,通过独立打包,也解决了因为Android系统的碎片化,Webview的版本不一,从而引起的应用体验(包括渲染能力和性能)不一致的问题。
Crosswalk发布一年左右就吸引了近千款应用基于Crosswalk构建,其中有数款应用都达到了超过百万级的下载量。不过后续由于Intel在移动平台上的战略调整,没有进一步演进。但这块的关键思路,后续或多或少在业界看到了相关的影子,比如Google后续推出的可独立升级的ChromeWebview,以及国内各互联网公司各自构建的WebView(腾讯的X5内核,阿里巴巴的UC内核等)。
Cordova+Crosswalk,一定程度上提升了基于Web的跨平台框架所需的API能力以及渲染性能,不过还有几个方面,还需要持续提升:
Ⅰ、开发范式/前端框架
标准的Web还是一种“半声明式”的开发方式,即通过HTML(Hyper Text Markup Langua-ge), CSS(Cascading Style Sheets)来描述整体页面结构和样式,但当要改变其中的界面元素时,开发者需要基于W3C DOM API,通过具体编程,来实现其中相关节点的定位以及增删改。当所面对的界面交互越复杂,所关联的数据越多,开发者负担就越重,也越容易出错。
2013年Facebook发布的React.js,引入了数据和UI自动绑定,以及组件化机制,将声明式的能力较好的融合到前端框架中。这是开发理念的一次比较大的进步。这样方式下,开发者无需去手动更改UI的结构,只需要描述好UI结构本身,以及数据和UI的绑定关系,框架层会自动跟踪数据的变化并更新相应的UI,这样进一步提升了UI框架开发效率。后续个人开发者尤雨溪推出的Vue.js框架本质上也是采用了类似的思路,只不过在表达方式以及具体实现上有所不同。另外,通过前端框架层提供的组件能力,本质上是对W3C HTML/CSS标准的进行了进一步封装,提供了更加高层的能力,这样有利于聚焦于相对常用的W3C标准能力,同时通过类似Virtual DOM的机制,对底层的Web引擎做了进一步的解耦,从而为后续的进一步演进建立了一定的基础。
Ⅱ、性能体验
由于W3C标准本身庞杂的历史积累和复杂性,相对应的Web引擎复杂度也非常高。复杂的渲染管线,千万量级的代码,百兆级的二进制大小,以及大几十兆甚至百兆级的基础内存占用,让基于Web引擎的应用在整体性能体验,资源占用等相关方面,尤其在移动平台上,和原生应用都有较大的差距,并难以较好解决。
2015年Facebook在React.js基础上推出的RN(React Native),是Web+Native的一个典型代表。RN的基本思路是开发范式上基于React.js,而具体渲染路径上,则完全绕过Web引擎,直接桥接到了操作系统原生的UI框架。2016年阿里巴巴推出的Weex也是采用了和RN类似的思路。
另外,针对RN的关键架构,Facebook持续做了不少演进:
1)布局引擎(Yoga)。2016年推出。通过实现CSS子集的模式实现高效的一致的跨平台布局体验;
2)JS引擎(Hermes)。2019年推出。针对移动平台上体验问题做相应改进,比如通过引入一定的AOT(Ahead Of Time)机制,主要是中间码预编译,来提升启动速度;
3)高效交互/按需加载等新架构。2022 年推出。支持高效的跨语言交互、数据共享,组件按需加载等相关机制。
通过这些相关的改进, RN实现了一定的平衡,基于Web的开发范式实现了较好的性能体验。不过,由于原生UI框架本身的差异,RN难以达成较好的跨平台一致性;另外由于需要额外一层Web到Native的桥接转换,和原生相比,RN在性能体验上天然就有一定差距,难以跨越。
Google在2018年推出的Flutter,则是借鉴了React的思想,走了另外一条较为创新的路。主要特征如下:
1)基于Dart语言的全新声明式范式设计,一切皆为Widget,可灵活组合,并通过数据驱动UI渲染
2)基于底层画布的高效自绘制能力
3)Dart运行时优化,比如高效的小对象分配释放能力,AOT机制等
再配合相对完整的跨平台能力,以及相应的工具链,Flutter具备了较好的综合竞争力。和类RN的方案相比,Flutter在以下几个方面具备一定优势:
1)跨平台一致性。通过自绘制机制,具备更好的跨平台一致性的高效的渲染能力。
2)语言执行性能。通过强类型语言Dart的引入以及相应的运行时优化(AOT等),具备更好的语言执行性能,理论上可对标iOS/Android原生语言。
不过,Flutter也有自身的不足:
1)语言生态。Dart语言生态和JS相比,有比较大的差距。而且生态培育过程一般都比较漫长。
2)动态化能力。Flutter尚不具备可对标JS相关框架的动态化部署机制,实现应用界面/业务的动态刷新,而这块又是大多数移动应用的强诉求。当然,这里有技术的因素,也有非技术的因素综合引起的。
另外一个层面,Flutter声明式UI的设计原则上更侧重灵活组合,暴露了较多的细粒度底层的机制(包括各种细粒度的Widget, 以及需进一步区分Widget的有状态和无状态等等),而在整体应用开发的简洁自然度方面,则考虑的相对较少。
受到Flutter的启发,业界又衍生出了一些新的方案。比如桥接标准的Web前端框架到Flutter,其目的是复用Web的生态优势,以及Flutter的高性能跨平台渲染能力。这块的典型代表是阿里巴巴2021年开源的Kraken,以及2022年进一步在此基础上演进的KUN。这种方案有一定程度的优势,不过由于它本质上还是桥接转换,另外引入了两种虚拟机(JS和Dart),架构上就决定了这种方案在性能和内存体验存在难以解决的缺陷。还有JS前端框架+ C/C++自绘制的方案,比如Weex2.0,它在一定程度上较好综合了JS层的生态和底层自绘制的优势,不过在语言运行时,开发的便捷度等方面,还缺少本质的改进。
总体而言,基于Web或通过Web衍生出来的跨平台框架,业界一直在持续的演进,包括Web API扩展,统一的持续优化的Web引擎,声明式前端框架,Web+Native的融合,自绘制机制,语言和框架深度融合的架构等等。但这些跨平台框架,离真正意义上的极简开发,极致性能,并可对标原生应用体验的设计方面,还缺少系统性的革新和跨越。
1.2.2 原生应用框架
1.2.2.1 iOS平台
iOS的原生应用框架是Cocoa Touch,其中的UI框架和语言最早分别是UIKit和OC(Objective-C),提供了传统的命令式(imperative)编程方式。2014年Apple推出了Swift语言,在简洁性,安全性,性能等方面都有进一步的提升。2019年,在Swift语言发布了5年之后,Apple推出了新一代的UI框架 – SwiftUI,在开发理念上做了一次全面升级:从命令式编程演进到了简洁自然的声明式(declarative)编程,并通过一套UI框架可开发Apple生态中的不同OS上的应用(iOS/iPadOS/watchOS/macOS等)。以下是几个比较重要的演进点:
a.全面采用声明式来描述UI,并且后续的UI变更都是通过数据驱动来完成。
具体而言,Apple重新定义了一整套开发范式,涵盖了UI的关键组成,UI和数据的关联等信息。整个UI就是一段描述,本质上就是描述界面的一个值,而不是任何实例;另外UI变化通过单一数据源来驱动(Apple称之为“Single Source of Truth”),而不是像之前命令式编程那样,开发者可以任意获取某个实例,定位到某个节点来进行更改。这跟传统的开发方式,有本质的不同。
b.简洁自然的开发范式。尽管在SwiftUI之前也有各种声明式编程框架,但SwiftUI在简洁性以及类自然语言的易理解性实现了极大的提升。具体而言,Apple通过语言和框架的深度结合,达成了简洁自然的开发体验。Swift的一些语言特性基本就是为SwiftUI服务,比如
1)Property Delegates(属性代理)
属性代理本质上一种语法糖机制,当访问指定的数据时,包括Get或Set,可以附加插入额外的处理逻辑。这个机制用来实现@State这类的装饰器,实现数据和UI之间的自动绑定,简化应用开发逻辑。
2)Trailing closure (尾随闭包)
尾随闭包主要用来增强可读性。当一个很长的闭包表达式作为最后一个参数传递给函数时,可以把它放在在函数括号之后。函数支持将其作为最后一个参数来调用。
3)Function Builders(函数构造器)
函数构造器也用来增强可读性,它可以用语句块作为接受参数列表,每行代码返回一个参数。
还有其他一些语法比如链式调用等等,这些共同组成了简洁自然的开发范式。
另外,SwiftUI中自定义组件的内容,其实是通过Function Builders返回的遵守View协议的类型组成,这就意味着框架运行时有机会结合编译时的UI类型信息做相应优化来实现视图变化的快速更新。
c.配套工具支持。在工具层面,除了传统的调试调测等能力,Apple的Xcode围绕SwiftUI预览做了比较重要的增强,简要说明如下:
1)实时双向预览。UI代码刷新可实时看到相应的界面效果,同时可实现代码-界面的双向预览 – 点击代码可看到的相应的UI界面,选择UI界面也可同步显示相应的代码。另外预览可以指定到组件级 – 通过加@Preview标签来指定相应组件进行预览
2)自定义预览。预览时可支持参数配置来定义预览的设备型号,暗黑模式,语言地区等上下文,并可以设置页面所依赖的入参等。
3)预览时动态交互,并可支持在预览器上调测。预览时可以实现常用的动态交互,比如手势、键盘等输入,音量、Home键、电源键等按键操作,以及网络、文件、多媒体能力支持等
这些预览相关的功能极大提升了应用的开发效率。本质上,高效的效果一致的预览是需要SwiftUI以及相应能力能够直接运行在PC(Personal Computer)平台上,才能达成较好的效果。
另外,从2022年SwiftUI 4.0的关键特性来看,Apple不断增强高级组件,以及自定义等相关能力,持续提升开发效率。比如更多的高级组件(各类图表,分享组件等),布局类型以及自定义布局能力增强(添加Grid网格布局,另外增强了自定义布局的能力,以及布局变化相关的动画)等等。
1.2.2.2 Android平台
Android的原生应用框架(Application Framework)主要包括应用管理,View 系统,后台服务(Service),内容提供者(Content Provider),广播接受机制(Broadcast Receiver)等。其中UI框架和语言最早分别是Android View系统以及Java,主要也是采用了命令式的开发模式(其中界面的初始声明可以通过XML(eXtensible Markup Language)方式来定义,后续的操作则都是通过相应的命令式API来完成)。2016年JetBrains公司正式发布Kotlin 1.0版本, 它是一种静态类型语言,提供了更加简洁,安全的语法特性(比如说解决Java的语法冗长以及空指针等问题)。同时,Kotlin在字节码级别和Java兼容。随着Kotlin的不断完善,再加上Java语言的版权问题等背后的原因,很快, 2019年Google宣布Kotlin为Android移动开发的首选语言。2021年,Google发布了基于Kotlin的声明式UI框架 – Jetpack Compose 1.0版本。本质上,Jetpack Compose和SwiftUI类似,都是声明式编程,都是单一可信数据源驱动UI变更。不过,也有几点不同:
1)Jetpack Compose中的界面表示为一切皆为可组合的函数。这些函数通常建议设计为无附带效应(即不会发生在可组合函数作用域之外的应用状态的变化)。从运行时维度,这些无附带效应的组合函数可并行执行。
2) Jetpack Compose整体开源,架构上则是提供了多层次的API,从底往上,提供了运行时, 界面,基础,Material设计系统的实现,每一层都是基于较低层的公共API构建。
3)跨平台能力。在Google发布 Jebpack Compose 1.0版本后,Jetbrains公司紧接着推出Compose Multiplatform项目,将Compose延伸到桌面平台(Windows, macOS, Linux),同时,配合Kotlin Multiplatform项目中的跨平台类库(网络、存储等),进一步简化基于Jetpack Compose的跨平台应用的开发。
在开发工具层面,Android Studio支持Jetpack Compose实时预览等特性,但目前成熟度相对弱一些,截至2022年,还未支持多设备预览,代码界面的双向预览,预览时调试,以及基础系统能力(比如网络/存储)的模拟等。
Google在2022/10/24给出的Jetpack Compose路线图中,Jetpack Compose接下来重点会围绕性能体验,高级组件,开发工具改进(包括预览和实时编辑),多平台支持(WearOS,大屏设备,主屏幕Widget)等方面展开。
总体而言,不管是原生框架,还是三方框架,除了性能体验,关键演进方向主要包括以下几点:
1)开发方式从命令式转为声明式;
2)语言和框架和工具结合更加紧密;
3)逐步增加多设备以及跨平台支持。
相关文章:
面向万物智联的应用框架的思考和探索(上)
原文:面向万物智联的应用框架的思考和探索(上),点击链接查看更多技术内容。 应用框架,是操作系统连接开发者生态,实现用户体验的关键基础设施。其中,开发效率和运行体验是永恒的诉求,…...
《Python机器学习基础教程》第1章学习笔记
目录 第1章 引言 1.1 为何选择机器学习 1.1.1 机器学习能够解决的问题 第1章 引言 机器学习又称为预测分析或统计学习,是一个交叉学科,是从数据中提取知识。 1.1 为何选择机器学习 智能应用早期,使用专家设计的规则体系来设计。 缺点&…...
ClickHouse 内存管理是如何实现的
概述 本文介绍Clickhouse内存管理的实现原理。通过本文的分析,可以对Clickhouse的内存管理有一个概要的理解。 Clickouse内存管理组成 ClickHouse 使用内存管理系统来控制内存资源的分配和释放。内存管理系统的主要组成部分是: 内存池:Cl…...
docker容器技术
什么是docker Docker 使用 Google 公司推出的 Go 语言 进行开发实现,基于 Linux 内核的 cgroup,namespace,以及 OverlayFS 类的 Union FS 等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术。由于隔离的进程独…...
设计模式七大设计原则
文章目录 1、什么是设计模式2、单一职责原则3、开闭原则4、接口隔离原则5、依赖倒置原则6、迪米特法则(最少知道原则)7、里式替换原则8、组合优于继承 设计模式主要是为了满足一个字 变,这个字,可能是需求变更、可能是场景变更&a…...
【Hello Network】TCP协议相关理解
作者:小萌新 专栏:网络 作者简介:大二学生 希望能和大家一起进步 本篇博客简介:补充下对于TCP协议的各种理解 TCP协议相关实验 TCP相关试验理解CLOSE_WAIT状态理解TIME_WAIT状态解决TIME_WAIT状态引起的bind失败的方法理解listen的…...
实施CRM目标有哪几步?如何制定CRM目标?
在当今竞争激烈的商业环境中,与客户建立持久的关系是企业重要的工作。CRM客户管理系统能有效帮助企业管理优化流程、管理客户,提高销售成功率,推动收入增长。那么您了解如何实施CRM吗?下面说说实施CRM目标是什么,如何设…...
船舶建造概论(船舶建造工艺任务与现代造船模式)
船舶建造概论 1 船舶建造概论1.1 船舶建造工艺主要任务1.2 船舶建造流程(1)钢材料预处理(2) 钢材料加工(3)分段制作(4)总段制作(5)船台合拢(6&…...
项目内训(2023.5.6)
目录 Nacos是什么? 领域模型是什么? domain模块一般是干什么的? 在小乌龟中合并其他分支的作用是什么? nacos的配置文件 服务集群、服务提供、服务更加灵活庞大、消费服务、访问比较麻烦,A和B服务一起访问 系统结…...
【操作系统OS】学习笔记第二章 进程与线程(下)【哈工大李治军老师】
基于本人观看学习 哈工大李治军老师主讲的操作系统课程 所做的笔记,仅进行交流分享。 特此鸣谢李治军老师,操作系统的神作! 如果本篇笔记帮助到了你,还请点赞 关注 支持一下 ♡>𖥦<)!! 主页专栏有更多࿰…...
Linux命令集(Linux文件管理命令--rmdir指令篇)
Linux命令集(Linux文件管理命令--rmdir指令篇) Linux文件管理命令集(rmdir指令篇)5. rmdir(remove directory)1. 删除空的目录 folder12. 强制删除目录 folder1(包括非空目录)3. 递归删除目录及其目录下所有…...
在技术圈超卷的当下,学历到底是敲门砖还是枷锁?
前言 最近,突然之间被“孔乙己文学”刷屏了,短时间内“孔乙己文学”迅速走红,孔乙己是中国文学中的一位经典人物,他的长衫被认为是他的象征之一,孔乙己的长衫折射出很多现象,既有社会的,也有教育…...
Linux cgroup
前言 Cgroup和namespace类似,也是将进程进程分组,但是目的与namespace不一样,namespace是为了隔离进程组之前的资源,而Cgroup是为了对一组进程进行统一的资源监控和限制。 Cgroup的组成 subsystem 一个subsystem就是一个内核模…...
PID整定二:基于Ziegler-Nichols的频域响应
PID整定二:基于Ziegler-Nichols的频域响应 1参考2连续Ziegler-Nichols方法的PID整定2.1整定方法2.2仿真示例 1参考 1.1根轨迹图的绘制及分析 1.2计算机控制技术01-3.4离散系统的根轨迹分析法 1.3PID控制算法学习笔记 2连续Ziegler-Nichols方法的PID整定 2.1整定…...
【tkinter 专栏】专栏前言
文章目录 前言本章内容导图1. tkinter 工具及特点2. 为什么使用 Python 进行 GUI 设计?2.1 Python 可以做什么2.2 使用 tkinter 可以干什么?3. 如何学习使用 tkinter 进行 GUI 设计?4. 开发环境搭建4.1 Python 的版本4.2 安装 Python4.2.1 下载 Python 安装包4.2.2 安装 Pyt…...
解决Linux中文字体模糊的4种方法
在Linux中,字体是非常重要的一部分,因为它们直接影响到用户的视觉体验。如果Linux字体模糊不清,那么用户将很难阅读文本,这将极大地降低用户的工作效率。本文将介绍Linux Mint中文字体模糊的问题,并提供一些解决方案。…...
【Android入门到项目实战-- 7.3】—— 如何调用手机摄像头和相册
目录 一、调用摄像头拍照 二、打开相册选择照片 学完本篇文章可以收获如何调用手机的摄像头和打开手机相册选择图片功能。 一、调用摄像头拍照 先新建一个CameraAlbumTest项目。 修改activity_main.xml,代码如下: 按钮打开摄像头,ImageView将拍到的…...
浅聊AIOT
引言 IoT是(Internet of Things)的简称,也就是人们常说的物联网;随着智能硬件的发展和推广,制造成本也随之下降,很多的厂家也慢慢地拥抱网络互联,逐步实现设备互联,也就进入了人们常说的万物互联时代。虽然…...
Python之模块和包(九)
1、模块 1、模块概述 模块是一个包含了定义的函数和变量等的文件。模块可以被程序引入,以使用该模块中的函数等功能。通俗讲:模块就好比是工具包,要想使用这个工具包中的工具(就好比函数),就需要导入这个模块。 2、import 在P…...
C++-----动态规划
目录 一、动态规划的基本思想 二、设计动态规划法的步骤 三、动态规划问题的特征 4.1 矩阵连乘积问题 4.1.1 分析最优解的结构 4.1.2 建立递归关系 4.1.3 计算最优值 4.1.3 计算最优值 4.1.3 构造最优解 4.2 动态规划算法的基本要素 4.2.1 最优子结构 4.2.2 重叠子问题 …...
2.2 Linux控制台访问CLI
系列文章目录 第1章 Linux Shell简介 第2章 Shell基础 <本章所在位置> 第3章 Bash Shell基础命令 第4章 Bash Shell命令进阶 第5章 Linux Shell深度理解 第6章 Linux环境变量 第7章 Linux文件权限 第8章 Linux文件系统的管理 第9章 Linux软件安装 第10章 Linux文本编辑器…...
代码随想录补打卡 509 斐波那契数列
代码如下 //斐波那契数列的第0项是0 第一项是1 func fib(n int) int { if n < 1 { return n } dp : make([]int,n1) dp[0] 0 dp[1] 1 for i : 2 ; i < n ; i { dp[i] dp[i-1] dp[i-2] } return dp[n] } 70 爬楼梯 代码如下 func climbStairs(n int) int …...
【每日一题Day195】LC1003检查替换后的词是否有效 | 栈
检查替换后的词是否有效【LC1003】 给你一个字符串 s ,请你判断它是否 有效 。 字符串 s 有效 需要满足:假设开始有一个空字符串 t "" ,你可以执行 任意次 下述操作将 t 转换为 s : 将字符串 "abc" 插入到 t…...
简单理解什么是序列化
为什么要序列化 序列化的目的就是为了对象可以在网络层进行传输, 比如通过后端传给前端数据。 什么是序列化 我们以Java为例。 序列化就是把对象转化为可传输的字节序列过程,这个字节序列可以是字符串,比如JSON格式的字符串,把…...
Django初识
1、简介 Django,是用python语言写的开源web开发框架,并遵循MVC设计。劳伦斯出版集团为了开发以新闻内容为主的网站,而开发出来了这个框架,于2005年7月在BSD许可证下发布。这个名称来源于比利时的爵士音乐家DjangoReinhardt&#…...
ARM嵌入式编译器-volatile关键字对编译器优化的影响
volatile限定符告知计算机,其他agent(而不是变量所在的程序)可以改变该变量的值。通常它被用于硬件地址以及在其他程序或同时运行的线程中共享数据。要求编译器不要对其描述的对象作优化处理,对它的读写都需要从内存中访问。 使用…...
销售数据分析怎么做?这篇文章说清楚了
如何分析销售数据?分析销售数据有哪些指标?销售数据分析有什么作用? 销售数据是不是得通过数据分析软件啊? 本文将为您解答疑惑—— 一、分析销售数据的指标 从两个层面上来讲,一个是对销售情况的整体把控…...
二十六、ISIS技术总结
文章目录 ISIS 概述一、路由协议总结1、路由优先级2、分类 二、ISIS 协议特点1、特点2、ISIS 路由器的种类 三、ISIS 配置1、基础配置2、network-entity含义3、router id 和系统id转换规则 四、ISIS 开销计算1、Narrow 模式2、Wide 模式 五、 ISIS 和 OSPF 的区别 ISIS 概述 I…...
三菱m70 m80系统解密 三菱m80机床到期解锁
我们从操作系统的发展讲起,为什么要有线程这个概念出现。《Java多线程学习笔记(一) 初遇篇》讲Java平台下的线程,如何使用和创建,以及引入线程后所面临的问题,为了解决线程安全问题,Java引入的机制,这也是《…...
InnoDB 磁盘结构之数据字典和双写缓冲区
数据字典(InnoDB Data Dictionary) MySQL中,数据字典包括了: 表结构、数据库名或表名、字段的数据类型、视图、索引、表字段信息、MySQL版本信息、存储过程、触发器等内容 InnoDB数据字典由内部系统表组成,这些表包含用于查找表…...
网站怎么做的支付/怎样推广自己的商城
场景说明 在执行任何的程序之前,必须确保程序和系统的版本位数是一致的,如果一种是x64,一种是32位的,就会出现上述的问题 具体例子 [rootjack 迅雷下载]# ./qt-opensource-linux-x64-5.7.0.run bash: ./qt-opensource-linux-x64-5.7.0.run: …...
微网站怎么样做线下活动吸粉/海外网站推广的公司
这天天气明朗,万里无云,是个放风筝的好日子。小红、小明和他们的好朋友小亮到草坪上放风筝。 他们来到目的地,发现草坪上有很多人都在放风筝。天空中,已经有勇猛的“老鹰”、有可爱的“金鱼”、还有长着无数只脚的“蜈蚣”……可…...
云网站7china/营销活动推广策划
前言 面试大概九十分钟,问的东西很全面,需要做充足准备,就是除了概念以外问的有点懵逼了。回来之后把这些题目做了一个分类并整理出答案(强迫症的我~狂补知识)分为MySQLJavaRedis算法网络Linux等六类,接下…...
沈阳专业网站建设公司排名/调研报告万能模板
Scala 是一门多范式(multi-paradigm)的编程语言,设计初衷是要集成面向对象编程和函数式编程的各种特性。Scala 运行在 Java 虚拟机上,并兼容现有的 Java 程序。 下面是我的scala学习笔记连接: Scala学习笔记&#x…...
网站制作的地方/网络营销服务商
静态字段缓存基本使用 /// <summary>/// 1 客户端缓存-CDN缓存-反向代理缓存-本地缓存/// 2 本地缓存原理和手写基础实现/// 3 缓存更新/过期/多线程测试 /// 4 缓存类库封装和缓存应用总结 /// </summary>/// <param name="args"></param&…...
建设一个网站app需要多少钱/一个新产品的营销方案
0效果 1来由 首先我有个程序需要用到进度条,我首先试了一下MATLAB自带的进度条: barwaitbar(0,读取数据中...); % waitbar显示进度条 for i1:1000A(i)rand();str[计算中...,num2str(100*i/1000),%]; % 显示的文本waitbar(i/1000,bar,str) …...