鸿蒙跨平台框架ArkUI-X
01
引言
目前,移动端主流跨平台方案有Flutter、React Native、uni-app等等,还有刚推出不久的Compose-Multiplatform,真所谓是百花齐放。这些框架各有特点,技术实现各有差异,比如Flutter通过Dart编写的UI描述对接Flutter渲染引擎,React Native 则是借助大前端成熟的发展背景,利用JS引擎生成UI描述,渲染时转化为原生控件,复用了原生渲染能力。至于选择哪种框架实现跨平台取决于项目的具体需求、开发团队的技能和偏好。今天我们探索一个新的框架——ArkUI-X。
02
ArkTS、ArkUI、ArkUI-X
在探索ArkUI-X之前,先了解一下ArkTS、ArkUI、ArkUI-X三者关系:
ArkTS 是华为基于TypeScript自研的开发语言,主要用于Harmony应用层开发。ArkTS在保持原 TS 基本语法风格的基础上,对 TS 的动态类型特性施加了更严格的约束,引入静态类型,减少运行时的类型检查,有助于性能提升;
ArkUI 是一套声明式UI开发框架。包含一系列UI组件(Text、Image)、状态管理(State、LocalStorage)、界面绘制、交互事件以及实时界面预览工具;
ArkUI-X 进一步将 ArkUI 扩展到多个 OS 平台,目前支持 OpenHarmony、HarmonyOS、Android、iOS,后续会逐步增加更多平台支持。
简单来说,开发者基于ArkUI框架,使用ArkTS语言进行编码,构建OpenHarmony/HarmonyOS应用,为了让应用运行到Android iOS上,利用 ArkUI-X 框架实现各OS平台的适配和构建。接下来我们将创建一个 ArkUI-X 简易Demo,通过Demo来探索ArkUI如何绘制组件到屏幕,ArkUI-X如何扩展ArkUI到Android平台,ArkUI-X如何与Android系统能力交互。
03
快速上手
3.1 环境搭建
DevEco Studio
首先从DevEco Studio官方网站(https://developer.huawei.com/consumer/cn/deveco-studio/)下载并安装DevEco Studio,需要选择4.0.0以上版本,以支持 ArkUI-X 套件。然后在DevEco Studio内部,分别下载HarmonyOS SDK 和 ArkUI-X,非合作企业开发者下载OpenHarmony SDK 和 ArkUI-X。
下载OpenHarmony SDK示例:

下载ArkUI-X示例:
Android Studio
因为最终要打出Android的apk实现跨平台,所以需要安装Android Studio。安装步骤对客户端小伙伴都已经轻车熟路了,强调一点:需要额外配置ANDROID_HOME(Android SDK安装路径)到系统环境变量中,这是步骤一中DevEco Studio编译项目的必备条件之一。
Xcode 同理,使用Xcode导入iOS项目,打IPA格式的安装包。
3.2 创建工程
完成上述的环境搭建后,就可以创建工程了。可以通过 ArkUI-X 基础模板进行创建。
创建完成后,得到这样一个工程结构:
entry:存放的是应用程序入口、核心业务逻辑以及资源文件。跨平台的公共源代码放在entry下,这点和纯Harmony项目结构一致;
.arkui-x/android:是一个标准的Android项目结构。但目前文件还不完整,需要Build App/Hap之后,才会生成更为完整的Android项目;
.arkui-x/iOS: 是一个标准的iOS项目结构,包含project.pbxproj。
Build App/Hap之后,在build目录下生成的后缀名.hap文件,可安装到HarmonyOS平台上。其它平台需要单独打包,.arkui-x下的Android项目导入到Android Studio中打出.apk;.arkui-x下的iOS项目导入到Xcode中打出.IPA。至此完成三个平台的打包工作。也就是说,在Build App过程中,ArkUI-X框架会把entry里公用ArkTS代码和resource,打入到各平台的安装包或项目文件中。
应用调试方面,目前只支持HarmonyOS调试,Android和iOS暂不支持ArkTS调试。
其实上述的环境搭建、新建项目、编译打包和安装调试,还有另一种方式实现——ACE Tools,是一套为ArkUI-X开发者提供的命令行工具。详情参见:ACE Tools快速指南(https://gitee.com/arkui-x/docs/blob/master/zh-cn/application-dev/quick-start/start-with-ace-tools.md)
04
窥探ArkUI的绘制过程
在了解 ArkUI-X 实现跨平台之前,我们先简单过一遍ArkTS编写的UI界面,是如何绘制到OpenHarmony/HarmonyOS上的,以上面的Demo为例:
// Index.ets
@Entry
@Component
struct Index {@State message: string = '今天星期五'build() {Row() {Column() {Text(this.message).fontSize(50).fontWeight(FontWeight.Bold)}.width('100%')}.height('100%')}
} Build App / Hap 之后得到hap包,和Android apk类似,对hap包进行解压得到modules.abc字节码文件 (Ark Byte Code),再对字节码文件进行16进制解析,可以看到这样一段代码:
class Index extends ViewPU {constructor(parent, params, __localStorage, elmtId = -1, paramsLambda = undefined, extraInfo) {super(parent, __localStorage, elmtId, extraInfo);this.__message = new ObservedPropertySimplePU('今天星期五', this, "message");this.setInitiallyProvidedValue(params);}setInitiallyProvidedValue(params: Index_Params) {if (params.message !== undefined) {this.message = params.message;}}aboutToBeDeleted() {this.__message.aboutToBeDeleted();SubscriberManager.Get().delete(this.id__());}private __message: ObservedPropertySimplePU<string>;initialRender() { // 编译器根据ArkTS中对组件的描述部分,重新生成jsthis.observeComponentCreation2((elmtId, isInitialRender) => {Row.create();Row.height('100%');}, Row);this.observeComponentCreation2((elmtId, isInitialRender) => {Column.create();Column.width('100%');}, Column);this.observeComponentCreation2((elmtId, isInitialRender) => {Text.create(this.message);Text.fontSize(50);Text.fontWeight(FontWeight.Bold);}, Text);Text.pop();Column.pop();Row.pop();}
} 可以看出,我们用@Component编写的组件,经过ArkCompiler编译后,会生成一个继承自ViewPU的js类,这个过程和kotlin经过kotlin编译器生成java有点类似。ViewPU位于ArkUI框架的arkui_ace_engine
(https://gitee.com/openharmony/arkui_ace_engine/tree/master)仓, 部分代码如下:
// 位于 frameworks/bridge/declarative_frontend/state_mgmt/src/lib/partial_update/pu_view.ts
abstract class ViewPU extends PUV2ViewBase implements IViewPropertiesChangeSubscriber, IView {constructor(parent: IView, localStorage: LocalStorage, elmtId: number = UINodeRegisterProxy.notRecordingDependencies, extraInfo: ExtraInfo = undefined) {super(parent, elmtId, extraInfo); this.id_ = SubscriberManager.MakeId() : elmtId;if (localStorage) {this.localStorage_ = localStorage;}SubscriberManager.Add(this);}public initialRenderView(): void {this.obtainOwnObservedProperties();this.initialRender();...}// 编译器生成的js类会实现该方法,主要是对组件的描述protected abstract initialRender(): void;// implements IMultiPropertiesChangeSubscriber UI状态变化回调viewPropertyHasChanged(varName: PropertyInfo, dependentElmtIds: Set<number>): void {if (dependentElmtIds.size && !this.isFirstRender()) { // 第一次走initialRenderView()if (!this.dirtDescendantElementIds_.size && !this.runReuse_) {this.markNeedUpdate(); // 更新UI 最终调到C++}...}let cb = this.watchedProps.get(varName);if (cb && typeof cb === 'function') {// ArkTS中@Prop @Watch('xxx') value 的invokecb.call(this, varName);}}
} 从上面ViewPU的部分代码,可以提取几点信息:
构造方法第一个参数
parent: IView,说明整个UI结构中存在子父组件概念,其内部维护一个子父组件关系链,这点和其它UI框架一样;构造逻辑依次是:
生成
element Id,用于局部刷新;定义
localStorage对象,用于页面状态共享;SubscriberManager.Add(this),添加订阅,监听状态变化。
状态变化后,回调viewPropertyHasChanged,更新UI并执行@Watch装饰器逻辑。
更多实现可查看源码,当然只需要看看流程即可,因为代码的commit频次比较高,每次打开看细节都可能有所变化,而且还存在很多同名v2类、v2方法。总之,ViewPU 是所有组件的基类,ViewPU 继承自 PUV2ViewBase,PUV2ViewBase 继承自 NativeViewPartialUpdate。从下面代码块的注释得知,UI渲染将在 C++ 里面实现,将通过NAPI(NAPI 和 JNI 类似)完成js与C++的交互。
// 位于 frameworks/bridge/declarative_frontend/state_mgmt/src/lib/puv2_common/puv2_view_base.ts 和 puv2_view_native_base.d.ts
// implemented in C++ for release
abstract class PUV2ViewBase extends NativeViewPartialUpdate {...
}/*** NativeViewPartialUpdate aka JSViewPartialUpdate C++ class exposed to JS* all definitions in this file are framework internal*/
declare class NativeViewPartialUpdate {constructor();markNeedUpdate(): void; // 更新UIfinishUpdateFunc(elmtId: number): void;...static create(newView: NativeViewPartialUpdate): void;
} markNeedUpdate()主要负责UI刷新,追踪一下它的实现逻辑:
// 位于 frameworks/bridge/declarative_frontend/jsview/js_view.cpp
void JSViewPartialUpdate::JSBind(BindingTarget object)
{JSClass<JSViewPartialUpdate>::Declare("NativeViewPartialUpdate");JSClass<JSViewPartialUpdate>::StaticMethod("create", &JSViewPartialUpdate::Create, opt);JSClass<JSViewPartialUpdate>::Method("markNeedUpdate", &JSViewPartialUpdate::MarkNeedUpdate);
}void JSViewPartialUpdate::MarkNeedUpdate()
{needsUpdate_ = ViewPartialUpdateModel::GetInstance()->MarkNeedUpdate(viewNode_);
} // 位于 frameworks/bridge/declarative_frontend/jsview/models/view_partial_update_model_impl.cpp
bool ViewPartialUpdateModelImpl::MarkNeedUpdate(const WeakPtr<AceType>& node)
{auto weakElement = AceType::DynamicCast<ComposedElement>(node);auto element = weakElement.Upgrade();if (element) {element->MarkDirty();}return true;
} ComposedElement 是 pipeline 记录组件信息的对象,weakElement.Upgrade() 将 ComposedElement 放入 pipeline 中,最终通过图形渲染引擎(OpenGL ES、Skia)完成显示。详细代码参考frameworks/core/pipeline/base/composed_element.cpp。
05
Android跨平台的实现
以上是一个hap包通过ArkUI完成渲染的大致过程,回到跨平台ArkUI-X,相同的ArkTS代码是如何运行在Android设备上的呢?
打开Android项目,看到assets下存放着ArkCompiler编译产物,和上一节中对.hap包解压后得到的文件一模一样。这是在编译环节中,编译脚本copy一份modules.abc字节码和resource到Android工程下,作为Android应用资源,打包时将以assets形式打入apk。
src/main/assets/arkui-x├── entry| ├── ets| | ├── modules.abc| | └── sourceMaps.map| ├── resouces.index| ├── resouces| └── module.json└── systemres 如何在Android上执行modules.abc字节码呢?打开libs,发现ArkUI相关的so动态库和jar包。
libs├── armabi-v7a| ├── libarkui_android.so| └── libhilog.so└── arkui_android_adapter.jar 其中libarkui_android.so 是 arkui_ace_engine、arkui_napi 、foundation/appframework、arkui_for_android... 所编译出的动态库,是运行和界面渲染的必要环境。另一个arkui_android_adapter.jar的功能是:Android Application需要继承arkui_android_adapter.jar包所提供的StageApplication。StageApplication用于初始化资源路径以及加载配置信息。Activity需要继承arkui_android_adapter.jar包所提供的StageActivity,StageActivity主要功能是将Android中Activity的生命周期与Harmony中Ability的生命周期进行映射。除此之外,arkui_android_adapter.jar适配了系统平台能力,如粘贴板、软键盘、字体、存储、日志。这里有个疑问:ArkUI-X是如何实现与Android系统之间的交互呢?ArkTS和Java没有相互调用的能力,为了实现ArkTS和Java交互,需要ArkTS与C++交互,C++再与Java交互,调用链为ArkTS -> NAPI -> C++ -> JNI -> Java,反之亦然,看起来十分复杂。ArkUI-X提供一套桥接能力,对于开发者来说,并不用关心这些封装逻辑,实际开发过程中,就像是ArkTS和Java直接交互。
下面通过粘贴板的例子,探究它的具体实现过程。我们给系统粘贴板设置数据——'明天星期六',使用ArkTS实现如下,看看最终是如何调到Android Framework 给粘贴板设置数据的api:ClipboardManager#setPrimaryClip()。
import pasteboard from '@ohos.pasteboard';Button('拷贝到粘贴板').onClick(() => {let pasteData: pasteboard.PasteData = pasteboard.createData(pasteboard.MIMETYPE_TEXT_PLAIN, '明天星期六')let systemPasteboard: pasteboard.SystemPasteboard = pasteboard.getSystemPasteboard()systemPasteboard.setData(pasteData)}) 这段代码对接ArkUI的调用链和上一节中渲染UI类似,就不再赘述了。粘贴板相关api 在 arkui_ace_engine中定义成抽象接口,如下:
// 位于 arkui_ace_engine/frameworks/core/common/clipboard/clipboard.h
namespace OHOS::Ace {class Clipboard : public AceType {DECLARE_ACE_TYPE(Clipboard, AceType);public:~Clipboard() override = default;virtual void SetData(const std::string& data, CopyOptions copyOption = CopyOptions::InApp, bool isDragData = false) = 0;}
} ArkUI-X 分平台对接口进行不同实现,Android的实现在arkui_for_android仓库中,其定义和实现如下,可见粘贴板设置数据api SetData()最终到ClipboardJni::SetData(data)
// 位于 arkui_for_android/capability/java/jni/clipboard/clipboard_impl.h
#include "core/common/clipboard/clipboard.h"namespace OHOS::Ace::Platform {class ClipboardImpl final : public Clipboard {public:explicit ClipboardImpl(const RefPtr<TaskExecutor>& taskExecutor) : Clipboard(taskExecutor) {}~ClipboardImpl() override = default;void SetData(const std::string& data, CopyOptions copyOption = CopyOptions::InApp, bool isDragData = false) override;}
} // 位于 arkui_for_android/capability/java/jni/clipboard/clipboard_impl.cpp
#include "adapter/android/capability/java/jni/clipboard/clipboard_impl.h"
#include "adapter/android/capability/java/jni/clipboard/clipboard_jni.h"namespace OHOS::Ace::Platform {void ClipboardImpl::SetData(const std::string& data, CopyOptions copyOption, bool isDragData){// 对 SetData 实现,最终ClipboardJni::SetData(data)taskExecutor_->PostTask([data] { ClipboardJni::SetData(data); }, TaskExecutor::TaskType::PLATFORM, "ArkUI-XClipboardImplSetData");}
} 再通过JNI实现C++和Java交互:
// 位于 arkui_for_android/capability/java/jni/clipboard/clipboard_jni.cpp
static const char CLIPBOARD_PLUGIN_CLASS_NAME[] = "ohos/ace/adapter/capability/clipboard/ClipboardPluginBase";
static const JNINativeMethod METHODS[] = {{ .name = "nativeInit", .signature = "()V", .fnPtr = reinterpret_cast<void*>(ClipboardJni::NativeInit) },
};
static const char METHOD_SET_DATA[] = "setData";
static const char SIGNATURE_SET_DATA[] = "(Ljava/lang/String;)V";// JNI_OnLoad
bool ClipboardJni::Register(std::shared_ptr<JNIEnv> env)
{// 动态注册 nativeInit 方法,java侧调用jclass clazz = env->FindClass(CLIPBOARD_PLUGIN_CLASS_NAME);bool ret = env->RegisterNatives(clazz, METHODS, ArraySize(METHODS)) == 0;return true;
}void ClipboardJni::NativeInit(JNIEnv* env, jobject object)
{jclass clazz = env->GetObjectClass(object);g_pluginMethods.setData = env->GetMethodID(clazz, METHOD_SET_DATA, SIGNATURE_SET_DATA);
}bool ClipboardJni::SetData(const std::string& data)
{auto env = JniEnvironment::GetInstance().GetJniEnv();jstring jData = env->NewStringUTF(data.c_str());// 反射调用 ClipboardPluginAosp.java setData方法env->CallVoidMethod(g_clipboardObj.get(), g_pluginMethods.setData, jData);if (jData != nullptr) {env->DeleteLocalRef(jData);}return true;
} 最终通过ClipboardManager#setData() ,将ArkTS中设置的内容,给到Android的系统粘贴板。
// 位于 arkui_for_android 仓库打出的 arkui_android_adapter.jar 包中
public class ClipboardPluginAosp extends ClipboardPluginBase {private final ClipboardManager clipManager;public ClipboardPluginAosp(Context context) {this.clipManager = (ClipboardManager context.getSystemService(Context.CLIPBOARD_SERVICE);nativeInit();}@Overridepublic void setData(String data) {if (clipManager != null) {ClipData clipData = ClipData.newPlainText(null, data);clipManager.setPrimaryClip(clipData);}}
} iOS平台的实现和Android平台类似,原理都是相通的。
06
小结
通过这一章,我们学到了ArkUI-X的环境搭建、项目创建和打包流程,探索了ArkTS编写的项目,编译后字节码文件如何与ArkUI对接,了解了ArkUI-X在Android平台上的实现方案,以及ArkUI-X如何适配系统平台能力。ArkUI-X 属于后来者,设计之初应该借鉴过其它跨平台方案,汲取了优秀设计,才形成目前的形态。今后在跨平台的实现上,我们又多了一种选择。
参考
ArkUI-X仓库地址:https://gitee.com/arkui-x
ArkUI-arkui_ace_engine仓库地址:https://gitee.com/openharmony/arkui_ace_engine
深入理解arkui_ace_engine:https://juejin.cn/post/7305235970286485515
相关文章:
鸿蒙跨平台框架ArkUI-X
01 引言 目前,移动端主流跨平台方案有Flutter、React Native、uni-app等等,还有刚推出不久的Compose-Multiplatform,真所谓是百花齐放。这些框架各有特点,技术实现各有差异,比如Flutter通过Dart编写的UI描述对接Flutte…...
第7章 wireshark(网络安全防御实战--蓝军武器库)
网络安全防御实战--蓝军武器库是2020年出版的,已经过去3年时间了,最近利用闲暇时间,抓紧吸收,总的来说,第7章开始学习抓包工具wireshark,如果你怀疑自己的电脑中毒了,那么用wireshark可以很轻松…...
【AI】神经网络|机器学习——图解Transformer(完整版)
Transformer是一种基于注意力机制的序列模型,最初由Google的研究团队提出并应用于机器翻译任务。与传统的循环神经网络(RNN)和卷积神经网络(CNN)不同,Transformer仅使用自注意力机制(self-attention)来处理输入序列和输出序列,因此可以并行计算,极大地提高了计算效率…...
002-SpringCloud-OpenFeign(远程调用)
SpringCloud-OpenFeign 1.引入依赖2.编写一个远程调用接口3.测试 1.引入依赖 <dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId> </dependency><dependencyManageme…...
基于类型的声明接收props
在 Vue 3 中,除了运行时声明这种常见方式,还可以通过基于类型的声明、解构赋值等方式来接收 props,下面为你详细介绍: 1. 基于类型的声明 这种方式借助 TypeScript 的类型系统来定义 props,具有类型检查和代码提示的…...
多方安全计算(MPC)电子拍卖系统
目录 一、前言二、多方安全计算(MPC)与电子拍卖系统概述2.1 多方安全计算(MPC)的基本概念2.2 电子拍卖系统背景与需求三、MPC电子拍卖系统设计原理3.1 系统总体架构3.2 电子拍卖中的安全协议3.3 数学与算法证明四、数据加解密模块设计五、GPU加速与系统性能优化六、GUI设计与系…...
使用QT + 文件IO + 鼠标拖拽事件 + 线程 ,实现大文件的传输
第一题、使用qss,通过线程,使进度条自己动起来 mythread.h #ifndef MYTHREAD_H #define MYTHREAD_H#include <QObject> #include <QThread> #include <QDebug>class mythread : public QThread {Q_OBJECT public:mythread(QObject* …...
【无人机路径规划】基于麻雀搜索算法(SSA)的无人机路径规划(Matlab)
效果一览 代码获取私信博主基于麻雀搜索算法(SSA)的无人机路径规划(Matlab) 一、算法背景与核心思想 麻雀搜索算法(Sparrow Search Algorithm, SSA)是一种受麻雀群体觅食行为启发的元启发式算法࿰…...
基于物联网技术的分布式光伏监控系统设计与实现
一、分布式光伏发电系统标准规范 1.常见应用场景 2.并网标准 Q/GDW1480-2015《分布式电源接入电网技术规定》 分布式电源并网电压等级可根据各并网点装机容量进行初步选择,推荐如下: 8kW 及以下可接入220V; 8kW~400kW可接入380V…...
阿里发布新开源视频生成模型Wan-Video,支持文生图和图生图,最低6G就能跑,ComFyUI可用!
Wan-Video 模型介绍:包括 Wan-Video-1.3B-T2V 和 Wan-Video-14B-T2V 两个版本,分别支持文本到视频(T2V)和图像到视频(I2V)生成。14B 版本需要更高的 VRAM 配置。 Wan2.1 是一套全面开放的视频基础模型&…...
27. Harmonyos Next仿uv-ui 组件NumberBox 步进器组件禁用状态
温馨提示:本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦! 文章目录 1. 组件介绍2. 效果展示3. 禁用状态设置3.1 整体禁用3.2 输入框禁用3.3 长按禁用 4. 完整示例代码5. 知识点讲解5.1 禁用状态属性5.2 禁用…...
【软件工程】一篇入门UML建模图(状态图、活动图、构件图、部署图)
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀软件开发必练内功_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前…...
AI智能导航站HTML5自适应源码帝国cms7.5模板
源码名称:AI导航站HTML5自适应源码帝国cms7.5模板 开发环境:帝国cms 7.5 安装环境:phpmysql var code "4d33ef8e-9e38-43b9-b37b-38f75944ecc9" 带软件采集,可以挂着自动采集发布,无需人工操作࿰…...
Redis 发布订阅模式详解:实现高效的消息通信
目录 引言 1. 什么是 Redis 发布订阅模式? 1.1 定义 1.2 核心概念 2. Redis 发布订阅的工作原理 2.1 基本流程 2.2 示例 2.3 频道与模式订阅 3. Redis 发布订阅的使用场景 3.1 实时消息通知 3.2 事件驱动架构 3.3 日志收集与分发 3.4 分布式锁与协调 4…...
ES的预置分词器
Elasticsearch(简称 ES)提供了多种预置的分词器(Analyzer),用于对文本进行分词处理。分词器通常由字符过滤器(Character Filters)、分词器(Tokenizer)和词元过滤器&#…...
MPPT与PWM充电原理及区别详解
MPPT(最大功率点跟踪)和PWM(脉宽调制)是太阳能充电控制器中常用的两种技术,它们在原理、效率和适用场景上有显著区别。以下是两者的详细对比: 1. 工作原理 PWM(脉宽调制) 核心机制…...
【AGI】通往AGI的复兴号:模型工具演进与技术路径优化
通往AGI的复兴号:模型工具演进与技术路径优化 一、核心模型与工具技术指标及场景分析1. 边缘计算标杆:GLM-PC(2024年11月)2. 长文本处理王者:DeepSeek R1(2025年1月)3. 轻量化开源代表ÿ…...
java2025年常见设计模式面试题
1. 请解释建造者模式(Builder Pattern)及其应用场景。 答案: 建造者模式用于创建一个复杂的对象,同时允许用户只通过指定复杂对象的类型和内容就能构建它们,隐藏了复杂的构建逻辑。 示例: public class C…...
探索CAMEL:揭开多智能体系统的神秘面纱
在人工智能领域,多智能体系统(Multi-Agent Systems, MAS)一直是一个充满活力和潜力的研究方向。随着大语言模型(LLM)的快速发展,智能体之间的协作与交互变得更加复杂和智能。今天,我们要介绍的是一个名为CAMEL(Communicative Agents for “Mind” Exploration of Large…...
el-pagination的使用说明
<el-paginationv-model:current-page"pageNo" //当前第几页v-model:page-size"pageSize" //每页显示多少条数据:page-sizes"[10, 20, 30]" //控制每页显示的条数:small"true" //控制分页器大小:disabled&quo…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
相机从app启动流程
一、流程框架图 二、具体流程分析 1、得到cameralist和对应的静态信息 目录如下: 重点代码分析: 启动相机前,先要通过getCameraIdList获取camera的个数以及id,然后可以通过getCameraCharacteristics获取对应id camera的capabilities(静态信息)进行一些openCamera前的…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
【论文阅读28】-CNN-BiLSTM-Attention-(2024)
本文把滑坡位移序列拆开、筛优质因子,再用 CNN-BiLSTM-Attention 来动态预测每个子序列,最后重构出总位移,预测效果超越传统模型。 文章目录 1 引言2 方法2.1 位移时间序列加性模型2.2 变分模态分解 (VMD) 具体步骤2.3.1 样本熵(S…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...
