【适配鸿蒙next】Flutter 新一代混合栈管理框架
前言
据最新消息显示,华为今年下半年将全面转向其自主平台HarmonyOS,放弃Android系统。
报道中提到,下一版HarmonyOS预计将随华为即将推出的Mate 70旗舰系列一起发布。
据悉,HarmonyOS Next 已经扩展到4000个应用程序,其中包括支付宝和麦当劳。
按照消息人士的说法,HarmonyOS Next的应用总数将在年内增至5000个,华为的目标是在短期内达到500000个。
HarmonyOS Next从零开始设计,由华为自主开发操作系统。虽然最初这套代码是为物联网设备编写,但华为很快意识到,它需要通过开发自己的操作系统来最大限度地降低外界的打压和限制。
事实上,华为正在通过自己的努力,让大家看到第三个主流智能手机操作系统,并与苹果的iOS和Android展开竞争。
本文主要讲Flutter 新一代混合栈管理框架
简介
Fusion 是新一代的混合栈管理框架,用于 Flutter 与 Native 页面统一管理,并支持页面通信、页面生命周期监听等功能。Fusion 即 融合,我们的设计初衷就是帮助开发者在使用 Flutter 与 Native 进行混合开发时尽量感受不到两者的隔阂,提升开发体验。此外,Fusion 彻底解决了混合开发过程中普遍存在的黑屏、白屏、闪屏等问题,更加适合重视用户体验的App使用。
从 4.0 开始,Fusion 已完成纯鸿蒙平台(HarmonyOS Next/OpenHarmony,以下简称 HarmonyOS)的适配,开发者可以在Android、iOS、HarmonyOS上得到完全一致的体验。(HarmonyOS 的 Flutter SDK 可以在这里获取)

OSAndroidiOSHarmonyOSSDK5.0(21)+11.0+4.1(11)+
Fusion 采用引擎复用方案,在 Flutter 与 Native 页面多次跳转情况下,APP 始终仅有一份 FlutterEngine 实例,因此拥有更好的性能和更低的内存占用。
Fusion 也是目前仅有的支持混合开发时应用在后台被系统回收后,所有Flutter页面均可正常恢复的混合栈框架。
开始使用
0、准备
在开始前需要按照 Flutter 官方文档,将 Flutter Module 项目接入到 Android、iOS、HarmonyOS 工程中。
1、初始化
Flutter 侧
使用 FusionApp 替换之前使用的 App Widget,并传入所需路由表,默认路由表和自定义路由表可单独设置也可同时设置。
void main() {runApp(FusionApp(// 默认路由表routeMap: routeMap,// 自定义路由表customRouteMap: customRouteMap,));
}// 默认路由表,使用默认的 PageRoute
// 使用统一的路由动画
final Map<String, FusionPageFactory> routeMap = {'/test': (arguments) => TestPage(arguments: arguments),kUnknownRoute: (arguments) => UnknownPage(arguments: arguments),
};// 自定义路由表,可自定义 PageRoute
// 比如:某些页面需要特定的路由动画则可使用该路由表
final Map<String, FusionPageCustomFactory> customRouteMap = {'/mine': (settings) => PageRouteBuilder(opaque: false,settings: settings,pageBuilder: (_, __, ___) => MinePage(arguments: settings.arguments as Map<String, dynamic>?)),
};
P.S: kUnknownRoute 表示未定义路由
注意:如果项目使用了 flutter_screenutil,需要在 runApp 前调用 Fusion.instance.install(),没有使用 flutter_screenutil则无须该步骤。
void main() {Fusion.instance.install();runApp(FusionApp(// 默认路由表routeMap: routeMap,// 自定义路由表customRouteMap: customRouteMap,));
}
Android 侧
在 Application 中进行初始化,并实现 FusionRouteDelegate 接口
class MyApplication : Application(), FusionRouteDelegate {override fun onCreate() {super.onCreate()Fusion.install(this, this)}override fun pushNativeRoute(name: String?, arguments: Map<String, Any>?) {// 根据路由 name 跳转对应 Native 页面}override fun pushFlutterRoute(name: String?, arguments: Map<String, Any>?) {// 根据路由 name 跳转对应 Flutter 页面// 可在 arguments 中存放参数判断是否需要打开透明页面}
}
iOS 侧
在 AppDelegate 中进行初始化,并实现 FusionRouteDelegate 代理
@UIApplicationMain
@objc class AppDelegate: UIResponder, UIApplicationDelegate, FusionRouteDelegate {func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {...Fusion.instance.install(self)...return true}func pushNativeRoute(name: String?, arguments: Dictionary<String, Any>?) {// 根据路由 name 跳转对应 Native 页面}func pushFlutterRoute(name: String?, arguments: Dictionary<String, Any>?) {// 根据路由 name 跳转对应 Flutter 页面// 可在 arguments 中存放参数判断是否需要打开透明页面// 可在 arguments 中存放参数判断是 push 还是 present}
}
HarmonyOS 侧
在 UIAbility 中进行初始化,并实现 FusionRouteDelegate 代理
export default class EntryAbility extends UIAbility implements FusionRouteDelegate {private static TAG = 'EntryAbility'private mainWindow: window.Window | null = nullprivate windowStage: window.WindowStage | null = nulloverride async onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): Promise<void> {await Fusion.instance.install(this.context, this)GeneratedPluginRegistrant.registerWith(Fusion.instance.defaultEngine!)}pushNativeRoute(name: string, args: Map<string, Object> | null): void {// 根据路由 name 跳转对应 Native 页面}pushFlutterRoute(name: string, args: Map<string, Object> | null): void {// 根据路由 name 跳转对应 Flutter 页面// 可在 arguments 中存放参数判断是否需要打开透明页面}
}
2、Flutter 容器
普通页面模式
Android 侧
通过 FusionActivity(或其子类) 创建 Flutter 容器,启动容器时需要使用 Fusion 提供的 buildFusionIntent 方法,其中参数 transparent 需设为 false。其 xml 配置参考如下(如果使用 FusionActivity 则不用配置):
<activityandroid:name=".CustomFusionActivity"android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"android:exported="false"android:hardwareAccelerated="true"android:launchMode="standard"android:theme="@style/FusionNormalTheme"android:windowSoftInputMode="adjustResize" />
iOS 侧
通过 FusionViewController (或其子类)创建 Flutter 容器,push 和 present 均支持。FusionViewController 默认隐藏了 UINavigationController。
在 iOS 中需要处理原生右滑退出手势和 Flutter 手势冲突的问题,解决方法也很简单:只需在自定义的 Flutter 容器中实现 FusionPopGestureHandler 并在对应方法中启用或者关闭原生手势即可,这样可以实现如果当前 Flutter 容器存在多个 Flutter 页面时,右滑手势是退出 Flutter 页面,而当 Flutter 页面只有一个时则右滑退出 Flutter 容器。
// 启用原生手势func enablePopGesture() {// 以下代码仅做演示,不可直接照搬,需根据APP实际情况自行实现navigationController?.interactivePopGestureRecognizer?.isEnabled = true}// 关闭原生手势func disablePopGesture() {// 以下代码仅做演示,不可直接照搬,需根据APP实际情况自行实现navigationController?.interactivePopGestureRecognizer?.isEnabled = false}
HarmonyOS 侧
通过 FusionEntry(或其子类) 创建 Flutter 容器,启动容器时需要使用 Fusion 提供的 buildFusionParams 方法,也可直接使用 FusionPage。默认全屏模式。
const params = buildFusionParams(name, args, false, backgroundColor)this.mainLocalStorage?.setOrCreate('params', params)router.pushNamedRoute({name: FusionConstant.FUSION_ROUTE_NAME})
透明页面模式
Android 侧
使用方式与普通页面模式相似,只是buildFusionIntent 方法的参数 transparent 需设为 true,其 xml 配置参考如下:
<activityandroid:name=".TransparentFusionActivity"android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"android:exported="false"android:hardwareAccelerated="true"android:launchMode="standard"android:theme="@style/FusionTransparentTheme"android:windowSoftInputMode="adjustResize" />
iOS 侧
使用方式与普通页面模式相似:
let fusionVc = CustomViewController(routeName: name, routeArguments: arguments, transparent: true)
navController?.present(fusionVc, animated: false)
HarmonyOS 侧
使用方式与普通页面模式相似:
const params = buildFusionParams(name, args, true, backgroundColor)this.windowStage?.createSubWindow(FusionConstant.TRANSPARENT_WINDOW, (_, win) => {const record: Record<string, Object> = {'params': params}win.loadContentByName(FusionConstant.FUSION_ROUTE_NAME, new LocalStorage(record))win.showWindow()})
Flutter 侧
同时Flutter页面背景也需要设置为透明
子页面模式
子页面模式是指一个或多个 Flutter 页面同时嵌入到 Native 容器中的场景,如:使用Tab切换Flutter和原生页面,Fusion 支持多个 Flutter 页面嵌入同一个 Native 容器中
Android 侧
使用 FusionFragment 以支持子页面模式,创建 FusionFragment 对象需要使用 buildFusionFragment 方法
iOS 侧
与页面模式一样使用 FusionViewController
HarmonyOS 侧
与页面模式一样使用 FusionEntry,配合 buildFusionParams方法配置参数
自定义容器背景色
默认情况下容器的背景为白色,这是因为考虑到绝大多数的页面都是使用白色背景,但如果打开的首个Flutter页面的背景是其他颜色,比如夜间模式下页面为深灰色,此时是为了更好的视觉效果,可以自定义容器的背景色与首个Flutter页面的背景色一致。
Android 侧
在 buildFusionIntent 和 buildFusionFragment方法中参数 backgroundColor 设为所需背景色
iOS 侧
在创建 FusionViewController (或其子类)对象时,参数 backgroundColor 设为所需背景色
HarmonyOS 侧
在 buildFusionParams方法中参数 backgroundColor 设为所需背景色
3、路由API(FusionNavigator)
○push:将对应路由入栈,Navigator.pushNamed 与之等同,根据FusionRouteType分为以下几种方式:
○flutter模式: 在当前Flutter容器中将指定路由对应的Flutter页面入栈,如果没有则跳转kUnknownRoute对应Flutter页面
○flutterWithContainer模式: 创建一个新的Flutter容器,并将指定路由对应的Flutter页面入栈,如果没有则跳转kUnknownRoute对应Flutter页面。即执行FusionRouteDelegate的pushFlutterRoute
○native模式: 将指定路由对应的Native页面入栈,即执行FusionRouteDelegate的pushNativeRoute
○adaption模式: 自适应模式,默认类型。首先判断该路由是否是Flutter路由,如果不是则进入native模式,如果是再判断当前是否是页面是否是Flutter容器,如果是则进入flutter模式,如果不是则进入flutterWithContainer模式
●pop:在当前Flutter容器中将栈顶路由出栈,Navigator.pop 与之等同
●maybePop:在当前Flutter容器中将栈顶路由出栈,可被WillPopScope拦截
●replace:在当前Flutter容器中将栈顶路由替换为对应路由,Navigator.pushReplacementNamed 与之等同
●remove:在当前Flutter容器中移除对应路由
路由跳转与关闭等操作既可使用FusionNavigator的 API,也可使用Navigator中与之对应的API(仅上述提到的部分)
4、Flutter Plugin 注册
在 Android 和 iOS 平台上框架内部会自动注册插件,无须手动调用 GeneratedPluginRegistrant.registerWith 进行注册,但 HarmonyOS 必须手动调用该方法。
5、自定义 Channel
如果需要 Native 与 Flutter 进行通信,则需要自行创建 Channel,创建 Channel 方式如下(以 MethodChannel 为例):
Android 侧
①、与容器无关的方法
在 Application 中进行注册
val channel = Fusion.defaultEngine?.dartExecutor?.binaryMessenger?.let {MethodChannel(it,"custom_channel")
}
channel?.setMethodCallHandler { call, result ->
}
②、与容器相关的方法
在自实现的 FusionActivity、FusionFragmentActivity、FusionFragment 上实现 FusionMessengerHandler 接口,在 configureFlutterChannel 中创建 Channel,在 releaseFlutterChannel 释放 Channel
class CustomActivity : FusionActivity(), FusionMessengerHandler {override fun configureFlutterChannel(binaryMessenger: BinaryMessenger) {val channel = MethodChannel(binaryMessenger, "custom_channel")channel.setMethodCallHandler { call, result -> }}override fun releaseFlutterChannel() {channel?.setMethodCallHandler(null)channel = null}
}
iOS 侧
①、与容器无关的方法
在 AppDelegate 中进行注册
var channel: FlutterMethodChannel? = nil
if let binaryMessenger = Fusion.instance.defaultEngine?.binaryMessenger {channel = FlutterMethodChannel(name: "custom_channel", binaryMessenger: binaryMessenger)
}
channel?.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in
}
②、与容器相关的方法
在自实现的 FusionViewController 上实现 FusionMessengerHandler 协议,在协议方法中创建 Channel
class CustomViewController : FusionViewController, FusionMessengerHandler {func configureFlutterChannel(binaryMessenger: FlutterBinaryMessenger) {channel = FlutterMethodChannel(name: "custom_channel", binaryMessenger: binaryMessenger)channel?.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) in}}func releaseFlutterChannel() {channel?.setMethodCallHandler(nil)channel = nil}
}
HarmonyOS 侧
①、与容器无关的方法
在 UIAbility 中进行注册
const binaryMessenger = Fusion.instance.defaultEngine?.dartExecutor.getBinaryMessenger()
const channel = new MethodChannel(binaryMessenger!, 'custom_channel')
channel.setMethodCallHandler({onMethodCall(call: MethodCall, result: MethodResult): void {}
})
②、与容器相关的方法
在自实现的 FusionEntry 上实现 FusionMessengerHandler 接口,在 configureFlutterChannel 中创建 Channel,在 releaseFlutterChannel 释放 Channel
export default class CustomFusionEntry extends FusionEntry implements FusionMessengerHandler, MethodCallHandler {private channel: MethodChannel | null = nullconfigureFlutterChannel(binaryMessenger: BinaryMessenger): void {this.channel = new MethodChannel(binaryMessenger, 'custom_channel')this.channel.setMethodCallHandler(this)}onMethodCall(call: MethodCall, result: MethodResult): void {result.success(`Custom Channel:${this}_${call.method}`)}releaseFlutterChannel(): void {this.channel?.setMethodCallHandler(null)this.channel = null}
}
BasicMessageChannel 和 EventChannel 使用也是类似
P.S.: 与容器相关的方法是与容器生命周期绑定的,如果容器不可见或者销毁了则无法收到Channel消息。
6、生命周期
应用生命周期监听:
①、在 Flutter 侧任意处注册监听皆可,并implements FusionAppLifecycleListener
②、根据实际情况决定是否需要注销监听
void main() {...FusionAppLifecycleBinding.instance.register(MyAppLifecycleListener());runApp(const MyApp());
}class MyAppLifecycleListener implements FusionAppLifecycleListener {@overridevoid onBackground() {print('onBackground');}@overridevoid onForeground() {print('onForeground');}
}
FusionAppLifecycleListener 生命周期回调函数:
●onForeground: 应用进入前台会被调用(首次启动不会被调用,Android 与 iOS 保持一致)
●onBackground: 应用退到后台会被调用
页面生命周期监听:
●①、在需要监听生命周期页面的 State 中 implements FusionPageLifecycleListener
●②、在 didChangeDependencies 中注册监听
●③、在 dispose 中注销监听
class LifecyclePage extends StatefulWidget {const LifecyclePage({Key? key}) : super(key: key);@overrideState<LifecyclePage> createState() => _LifecyclePageState();
}class _LifecyclePageState extends State<LifecyclePage>implements FusionPageLifecycleListener {@overrideWidget build(BuildContext context) {return Container();}@overridevoid didChangeDependencies() {super.didChangeDependencies();FusionPageLifecycleBinding.instance.register(this);}@overridevoid onPageVisible() {}@overridevoid onPageInvisible() {}@overridevoid onForeground() {}@overridevoid onBackground() {}@overridevoid dispose() {super.dispose();FusionPageLifecycleBinding.instance.unregister(this);}
}
PageLifecycleListener 生命周期回调函数:
●onForeground: 应用进入前台会被调用,所有注册了生命周期监听的页面都会收到
●onBackground: 应用退到后台会被调用,所有注册了生命周期监听的页面都会收到
●onPageVisible: 该 Flutter 页面可见时被调用,如:从 Native 页面或其他 Flutter 页面 push 到该 Flutter 页面时;从 Native 页面或其他 Flutter 页面 pop 到该 Flutter 页面时;应用进入前台时也会被调用。
●onPageInvisible: 该 Flutter 页面不可见时被调用,如:从该 Flutter 页面 push 到 Native 页面或其他 Flutter 页面时;如从该 Flutter 页面 pop 到 Native 页面或其他 Flutter 页面时;应用退到后台时也会被调用。
7、全局通信
支持消息在应用中的传递,可以指定 Native 还是 Flutter 或者全局接收和发送。
注册消息监听
Flutter侧
●①、在需要监听消息的类中 implements FusionNotificationListener,并复写 onReceive 方法,该方法可收到发送过来的消息
●②、在合适时机注册监听
●③、在合适时机注销监听
class TestPage extends StatefulWidget {@overrideState<TestPage> createState() => _TestPageState();
}class _TestPageState extends State<TestPage> implements FusionNotificationListener {@overridevoid onReceive(String name, Map<String, dynamic>? body) {}@overridevoid didChangeDependencies() {super.didChangeDependencies();FusionNotificationBinding.instance.register(this);}@overridevoid dispose() {super.dispose();FusionNotificationBinding.instance.unregister(this);}
}
Native侧
●①、在需要监听消息的类中实现 FusionNotificationListener 接口,并复写 onReceive 方法,该方法可收到发送过来的消息
●②、在适当时机使用 FusionNotificationBinding 的 register 方法注册监听
●③、在适当时机使用 FusionNotificationBinding 的 unregister 方法注销监听
发送消息
三端均可使用FusionNavigator 的 sendMessage 方法来发送消息,根据使用FusionNotificationType 不同类型有不同效果:
●flutter: 仅 Flutter 可以收到
●native: 仅 Native 可以收到
●global(默认): Flutter 和 Native 都可以收到
8、返回拦截
在纯 Flutter 开发中可以使用WillPopScope组件拦截返回操作,Fusion 也完整支持该功能,使用方式与在纯 Flutter 开发完全一致,此外使用FusionNavigator.maybePop的操作也可被WillPopScope组件拦截。
9、状态恢复
Fusion 支持 Android 和 iOS 平台 APP 被回收后 Flutter 路由的恢复。
总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。随着鸿蒙的不断发展以及国家的大力支持,未来鸿蒙职位肯定会迎来一个大的爆发,只有积极应对变化,不断学习和提升自己,我们才能在这个变革的时代中立于不败之地。

相关文章:
【适配鸿蒙next】Flutter 新一代混合栈管理框架
前言 据最新消息显示,华为今年下半年将全面转向其自主平台HarmonyOS,放弃Android系统。 报道中提到,下一版HarmonyOS预计将随华为即将推出的Mate 70旗舰系列一起发布。 据悉,HarmonyOS Next 已经扩展到4000个应用程序,…...
车载电子电气架构 --- 车载信息安全
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和事,多看一眼都是你的不对。非必要不费力证明自己,无利益不试图说服别人,是精神上的节…...
【数据结构(邓俊辉)学习笔记】图04——双连通域分解
文章目录 0. 概述1 关节点与双连通域2 蛮力算法3 可行算法4 实现5 示例6 复杂度 0. 概述 学习下双连通域分解,这里略微有一点点难,这个算是DFS算法的非常非常经典的应用,解决的问题也非常非常有用。 1 关节点与双连通域 连通性很好理解&am…...
UI学习(二)
UI学习(二) 文章目录 UI学习(二)布局子视图手动布局自动布局 导航控制器导航控制器基础导航控制器的切换导航栏工具栏 分栏控制器分栏控制器协议部分的内容UITableView基础部分相关的协议函数高级协议与单元格 多界面传值 布局子视…...
【嵌入式】波特率9600,发送8个字节需要多少时间,如何计算?
问题: 波特率9600,发送 01 03 00 00 00 04 44 09 (8字节) 需要多少时间,如何计算? 在计算发送数据的时间时,首先要考虑波特率以及每个字符的数据格式。对于波特率9600和标准的UART数据格式(1个起始位&…...
jmeter -n -t 使用非GUI模式运行脚本说明
命令模式下执行jmx文件 jmeter -n -t fatie.jmx -l results\t4.jtl -e -o results\h1 表示以命令行模式运行当前目录下的脚本fatie.jmx,将结果存入当前目录下的results\t1.jtl,并且生成html格式的报告,写入文件夹results\h1。 说明:生成结果的文件夹r…...
网络流媒体协议——HLS协议
HTTP 实时流媒体(HTTP Live Streaming,HLS)协议是苹果公司提出的主要用于直播的流媒体协议。一个完整的基于HLS协议的流媒体直播系统由四部分组成,即音视频采集器、媒体服务器、媒体分发器和播放客户端。 媒体服务器 媒体服务器的…...
Linux服务器扩容及磁盘分区(LVM和非LVM)
Linux扩容及磁盘分区(LVM和非LVM) 本文主要介绍了阿里云服务器centos的扩容方法:非LVM分区扩容方法(系统盘),以及磁盘改LVM并分区(数据盘)。主要是ext4文件系统及xfs磁盘scsi MBR分…...
支持向量机
支持向量机(SVM) 支持向量机(Support Vector Machine, SVM)是一种用于分类和回归任务的监督学习算法。SVM 的核心思想是找到一个最优的决策边界(或称为超平面),以最大化不同类别之间的间隔。以…...
Kafka 架构
1 整体架构 1.1 Zookeeper Zookeeper 是一个分布式协调服务,用于管理 Kafka 的元数据。它负责维护 Kafka 集群的配置信息、Broker 列表和分区的 Leader 信息。 Zookeeper 确保了 Kafka 集群的高可用性和可靠性。 但 Zookeeper 已经成为 Kafka 性能瓶颈,…...
iOS 查看runtime源码的几种方法
目录 前言 查看runtime 源码方法 1.下载 Apple 官方提供的源代码 2.通过 GitHub 访问镜像 3.使用命令行工具查看 4.示例 前言 这篇博客主要介绍了查看iOS runtime源代码的方法。 查看runtime 源码方法 查看iOS runtime源码的方法包括以下几个步骤: 1.下载 A…...
底板外设倒灌到处理器分析
在嵌入式系统中,底板外设通常与处理器通过各种接口(如UART、SPI、I2C、GPIO等)进行连接。这些外设可能包括传感器、执行器、存储器、通信模块等。倒灌是指当外设向处理器提供的信号电平超出了处理器能够接受的范围,导致处理器无法…...
使用贝塞尔曲线实现一个iOS时间轴
UI效果 实现的思路 就是通过贝塞尔曲线画出时间轴的圆环的路径,然后 使用CAShaper来渲染UI,再通过 animation.beginTime [cilrclLayer convertTime:CACurrentMediaTime() fromLayer:nil] circleTimeOffset 来设置每个圆环的动画开始时间, …...
【深度学习】深度学习之巅:在 CentOS 7 上打造完美Python 3.10 与 PyTorch 2.3.0 环境
【深度学习】深度学习之巅:在 CentOS 7 上打造完美Python 3.10 与 PyTorch 2.3.0 环境 大家好 我是寸铁👊 总结了一篇【深度学习】深度学习之巅:在 CentOS 7 上打造完美Python 3.10 与 PyTorch 2.3.0 环境✨ 喜欢的小伙伴可以点点关注 &#…...
在docker容器中使用gdb调试python3.11的进程
gdb调试python进程的前提条件 安装python及python调试信息安装gdb工具安装python-gdb.py扩展 安装过程 我们使用docker来安装以上内容,Dockerfile文件内容如下: FROM docker.io/centos:7.4.1708# 安装依赖 RUN yum install -y -q epel-release &…...
堆排序要点和难点以及具体案例应用
堆排序(Heap Sort)是一种基于堆数据结构的排序算法。下面我将以分点表示和归纳的方式,结合相关数字和信息,详细描述堆排序的PTA(Programming and Testing Approach,编程与测试方法)。 1. 堆排序原理 堆排序是一种树形选择排序,利用了完全二叉树的性质,通过构建最大堆…...
pyspark中使用mysql jdbc报错java.lang.ClassNotFoundException: com.mysql.jdbc.Driver解决
报错信息: py4j.protocol.Py4JJavaError: An error occurred while calling o33.load. : java.lang.ClassNotFoundException: com.mysql.jdbc.Driver 我的解决方法: 这个报错就是提示你找不到jar包,所以你需要去下载一个和你mysql版本匹配的j…...
对称加密系统解析
目录 1.概述 2. 对称密码类型 3. 对称加密优缺点 4. 对称加密算法 4.1 DES 4.2 3DES 4.3 AES 4.4 SM1 4.5 SM4 1.概述 对称加密,是指在加密和解密时使用同一秘钥的方式。秘钥的传送和保存的保护非常重要,务必不要让秘…...
初识 java 2
1. idea 的调试 1. 点击鼠标左键设置断点 2.运行到断点处 点击 或点击鼠标右键,再点击 使代码运行到断点处,得到 2. 输出到控制台 System.out.println(value);//输出指定的内容,并换行 value 要打印的内容System.out.print(value);…...
云端狂飙:Django项目部署与性能优化的极速之旅
Hello,我是阿佑,这次阿佑将手把手带你亲自踏上Django项目从单机到云端的全过程,以及如何通过Docker实现项目的无缝迁移和扩展。不仅详细介绍了Docker的基本概念和操作,还深入探讨Docker Compose、Swarm和Kubernetes等高级工具的使…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能
下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能,包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...
无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
智能在线客服平台:数字化时代企业连接用户的 AI 中枢
随着互联网技术的飞速发展,消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁,不仅优化了客户体验,还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用,并…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...
浪潮交换机配置track检测实现高速公路收费网络主备切换NQA
浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求,本次涉及的主要是收费汇聚交换机的配置,浪潮网络设备在高速项目很少,通…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
