HarmonyOS4.0系统性深入开发08服务卡片架构

服务卡片概述

服务卡片(以下简称“卡片”)是一种界面展示形式,可以将应用的重要信息或操作前置到卡片,以达到服务直达、减少体验层级的目的。卡片常用于嵌入到其他应用(当前卡片使用方只支持系统应用,如桌面)中作为其界面显示的一部分,并支持拉起页面、发送消息等基础的交互功能。

服务卡片架构

图1 服务卡片架构
点击放大

卡片的基本概念:

  • 卡片使用方:如上图中的桌面,显示卡片内容的宿主应用,控制卡片在宿主中展示的位置。
    • 应用图标:应用入口图标,点击后可拉起应用进程,图标内容不支持交互。
    • 卡片:具备不同规格大小的界面展示,卡片的内容可以进行交互,如实现按钮进行界面的刷新、应用的跳转等。
  • 卡片提供方:包含卡片的应用,提供卡片的显示内容、控件布局以及控件点击处理逻辑。
    • FormExtensionAbility:卡片业务逻辑模块,提供卡片创建、销毁、刷新等生命周期回调。
    • 卡片页面:卡片UI模块,包含页面控件、布局、事件等显示和交互信息。

卡片的常见使用步骤如下。

图2 卡片常见使用步骤
点击放大

  1. 长按“桌面图标”,弹出操作菜单。
  2. 点击“服务卡片”选项,进入卡片预览界面。
  3. 点击“添加到桌面”按钮,即可在桌面上看到新添加的卡片。

服务卡片UI页面开发方式

在Stage模型下,服务卡片的UI页面支持通过ArkTS和JS两种语言进行开发:

  • 基于声明式范式ArkTS UI开发的卡片,简称ArkTS卡片。
  • 基于类Web范式JS UI开发的卡片,简称JS卡片。

ArkTS卡片与JS卡片具备不同的实现原理及特征,在场景能力上的差异如下表所示。

类别JS卡片ArkTS卡片
开发范式类Web范式声明式范式
组件能力支持支持
布局能力支持支持
事件能力支持支持
自定义动效不支持支持
自定义绘制不支持支持
逻辑代码执行(不包含import能力)不支持支持

相比于JS卡片,ArkTS卡片在能力和场景方面更加丰富,因此无论开发何种用途的卡片,都推荐使用ArkTS卡片,因为它可以提高开发效率并实现动态化。但如果只需要做静态页面展示的卡片,可以考虑使用JS卡片。

开发基于JS UI的卡片

以下内容介绍基于类Web范式的JS UI卡片开发指南。

运作机制

卡片框架的运作机制如图1所示。

图1 卡片框架运作机制(Stage模型)

点击放大

卡片使用方包含以下模块:

  • 卡片使用:包含卡片的创建、删除、请求更新等操作。
  • 通信适配层:由OpenHarmony SDK提供,负责与卡片管理服务通信,用于将卡片的相关操作到卡片管理服务。

卡片管理服务包含以下模块:

  • 周期性刷新:在卡片添加后,根据卡片的刷新策略启动定时任务周期性触发卡片的刷新。
  • 卡片缓存管理:在卡片添加到卡片管理服务后,对卡片的视图信息进行缓存,以便下次获取卡片时可以直接返回缓存数据,降低时延。
  • 卡片生命周期管理:对于卡片切换到后台或者被遮挡时,暂停卡片的刷新;以及卡片的升级/卸载场景下对卡片数据的更新和清理。
  • 卡片使用方对象管理:对卡片使用方的RPC对象进行管理,用于使用方请求进行校验以及对卡片更新后的回调处理。
  • 通信适配层:负责与卡片使用方和提供方进行RPC通信。

卡片提供方包含以下模块:

  • 卡片服务:由卡片提供方开发者实现,开发者实现生命周期处理创建卡片、更新卡片以及删除卡片等请求,提供相应的卡片服务。
  • 卡片提供方实例管理模块:由卡片提供方开发者实现,负责对卡片管理服务分配的卡片实例进行持久化管理。
  • 通信适配层:由OpenHarmony SDK提供,负责与卡片管理服务通信,用于将卡片的更新数据主动推送到卡片管理服务。

说明

实际开发时只需要作为卡片提供方进行卡片内容的开发,卡片使用方和卡片管理服务由系统自动处理。

接口说明

FormExtensionAbility类拥有如下API接口,具体的API介绍详见接口文档。

接口名描述
onAddForm(want: Want): formBindingData.FormBindingData卡片提供方接收创建卡片的通知接口。
onCastToNormalForm(formId: string): void卡片提供方接收临时卡片转常态卡片的通知接口。
onUpdateForm(formId: string): void卡片提供方接收更新卡片的通知接口。
onChangeFormVisibility(newStatus: { [key: string]: number }): void卡片提供方接收修改可见性的通知接口。
onFormEvent(formId: string, message: string): void卡片提供方接收处理卡片事件的通知接口。
onRemoveForm(formId: string): void卡片提供方接收销毁卡片的通知接口。
onConfigurationUpdate(config: Configuration): void当系统配置更新时调用。
onShareForm?(formId: string): { [key: string]: any }卡片提供方接收卡片分享的通知接口。

formProvider类有如下API接口,具体的API介绍详见接口文档。

接口名描述
setFormNextRefreshTime(formId: string, minute: number, callback: AsyncCallback): void;设置指定卡片的下一次更新时间。
setFormNextRefreshTime(formId: string, minute: number): Promise;设置指定卡片的下一次更新时间,以promise方式返回。
updateForm(formId: string, formBindingData: FormBindingData, callback: AsyncCallback): void;更新指定的卡片。
updateForm(formId: string, formBindingData: FormBindingData): Promise;更新指定的卡片,以promise方式返回。

formBindingData类有如下API接口,具体的API介绍详见接口文档。

接口名描述
createFormBindingData(obj?: Object | string): FormBindingData创建一个FormBindingData对象。

开发步骤

Stage卡片开发,即基于Stage模型的卡片提供方开发,主要涉及如下关键步骤:

  • 创建卡片FormExtensionAbility:卡片生命周期回调函数FormExtensionAbility开发。
  • 配置卡片配置文件:配置应用配置文件module.json5和profile配置文件。
  • 卡片信息的持久化:对卡片信息进行持久化管理。
  • 卡片数据交互:通过updateForm更新卡片显示的信息。
  • 开发卡片页面:使用HML+CSS+JSON开发JS卡片页面。
  • 开发卡片事件:为卡片添加router事件和message事件。

创建卡片FormExtensionAbility

创建Stage模型的卡片,需实现FormExtensionAbility生命周期接口。先参考DevEco Studio服务卡片开发指南生成服务卡片模板。

  1. 在EntryFormAbility.ts中,导入相关模块。

    import FormExtensionAbility from '@ohos.app.form.FormExtensionAbility';
    import formBindingData from '@ohos.app.form.formBindingData';
    import formInfo from '@ohos.app.form.formInfo';
    import formProvider from '@ohos.app.form.formProvider';
    import dataStorage from '@ohos.data.storage';
    
  2. 在EntryFormAbility.ts中,实现FormExtension生命周期接口。

    export default class EntryFormAbility extends FormExtensionAbility {onAddForm(want) {console.info('[EntryFormAbility] onAddForm');// 使用方创建卡片时触发,提供方需要返回卡片数据绑定类let obj = {"title": "titleOnCreate","detail": "detailOnCreate"};let formData = formBindingData.createFormBindingData(obj);return formData;}onCastToNormalForm(formId) {// 使用方将临时卡片转换为常态卡片触发,提供方需要做相应的处理console.info('[EntryFormAbility] onCastToNormalForm');}onUpdateForm(formId) {// 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要重写该方法以支持数据更新console.info('[EntryFormAbility] onUpdateForm');let obj = {"title": "titleOnUpdate","detail": "detailOnUpdate"};let formData = formBindingData.createFormBindingData(obj);formProvider.updateForm(formId, formData).catch((error) => {console.info('[EntryFormAbility] updateForm, error:' + JSON.stringify(error));});}onChangeFormVisibility(newStatus) {// 使用方发起可见或者不可见通知触发,提供方需要做相应的处理,仅系统应用生效console.info('[EntryFormAbility] onChangeFormVisibility');}onFormEvent(formId, message) {// 若卡片支持触发事件,则需要重写该方法并实现对事件的触发console.info('[EntryFormAbility] onFormEvent');}onRemoveForm(formId) {// 删除卡片实例数据console.info('[EntryFormAbility] onRemoveForm');}onConfigurationUpdate(config) {console.info('[EntryFormAbility] nConfigurationUpdate, config:' + JSON.stringify(config));}onAcquireFormState(want) {return formInfo.FormState.READY;}
    }
    

说明

FormExtensionAbility不能常驻后台,即在卡片生命周期回调函数中无法处理长时间的任务。

配置卡片配置文件

  1. 卡片需要在module.json5配置文件中的extensionAbilities标签下,配置ExtensionAbility相关信息。FormExtensionAbility需要填写metadata元信息标签,其中键名称为固定字符串"ohos.extension.form",资源为卡片的具体配置信息的索引。

    配置示例如下:

    {"module": {..."extensionAbilities": [{"name": "EntryFormAbility","srcEntrance": "./ets/entryformability/EntryFormAbility.ts","label": "$string:EntryFormAbility_label","description": "$string:EntryFormAbility_desc","type": "form","metadata": [{"name": "ohos.extension.form","resource": "$profile:form_config"}]}]}
    }
    
  2. 卡片的具体配置信息。在上述FormExtensionAbility的元信息("metadata"配置项)中,可以指定卡片具体配置信息的资源索引。例如当resource指定为$profile:form_config时,会使用开发视图的resources/base/profile/目录下的form_config.json作为卡片profile配置文件。内部字段结构说明如下表所示。

    表1 卡片profile配置文件

    属性名称含义数据类型是否可缺省
    name表示卡片的类名,字符串最大长度为127字节。字符串
    description表示卡片的描述。取值可以是描述性内容,也可以是对描述性内容的资源索引,以支持多语言。字符串最大长度为255字节。字符串可缺省,缺省为空。
    src表示卡片对应的UI代码的完整路径。字符串
    window用于定义与显示窗口相关的配置。对象可缺省
    isDefault表示该卡片是否为默认卡片,每个UIAbility有且只有一个默认卡片。- true:默认卡片。- false:非默认卡片。布尔值
    colorMode表示卡片的主题样式,取值范围如下:- auto:自适应。- dark:深色主题。- light:浅色主题。字符串可缺省,缺省值为“auto”。
    supportDimensions表示卡片支持的外观规格,取值范围:- 1 * 2:表示1行2列的二宫格。- 2 * 2:表示2行2列的四宫格。- 2 * 4:表示2行4列的八宫格。- 4 * 4:表示4行4列的十六宫格。字符串数组
    defaultDimension表示卡片的默认外观规格,取值必须在该卡片supportDimensions配置的列表中。字符串
    updateEnabled表示卡片是否支持周期性刷新,取值范围:- true:表示支持周期性刷新,可以在定时刷新(updateDuration)和定点刷新(scheduledUpdateTime)两种方式任选其一,优先选择定时刷新。- false:表示不支持周期性刷新。布尔类型
    scheduledUpdateTime表示卡片的定点刷新的时刻,采用24小时制,精确到分钟。updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。字符串可缺省,缺省值为“0:0”。
    updateDuration表示卡片定时刷新的更新周期,单位为30分钟,取值为自然数。当取值为0时,表示该参数不生效。当取值为正整数N时,表示刷新周期为30*N分钟。updateDuration参数优先级高于scheduledUpdateTime,两者同时配置时,以updateDuration配置的刷新时间为准。数值可缺省,缺省值为“0”。
    formConfigAbility表示卡片的配置跳转链接,采用URI格式。字符串可缺省,缺省值为空。
    formVisibleNotify标识是否允许卡片使用卡片可见性通知。字符串可缺省,缺省值为空。
    metaData表示卡片的自定义信息,包含customizeData数组标签。对象可缺省,缺省值为空。

    配置示例如下:

    {"forms": [{"name": "widget","description": "This is a service widget.","src": "./js/widget/pages/index/index","window": {"designWidth": 720,"autoDesignWidth": true},"colorMode": "auto","isDefault": true,"updateEnabled": true,"scheduledUpdateTime": "10:30","updateDuration": 1,"defaultDimension": "2*2","supportDimensions": ["2*2"]}]
    }
    

卡片信息的持久化

因大部分卡片提供方都不是常驻服务,只有在需要使用时才会被拉起获取卡片信息,且卡片管理服务支持对卡片进行多实例管理,卡片ID对应实例ID,因此若卡片提供方支持对卡片数据进行配置,则需要对卡片的业务数据按照卡片ID进行持久化管理,以便在后续获取、更新以及拉起时能获取到正确的卡片业务数据。

const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store";
async function storeFormInfo(formId: string, formName: string, tempFlag: boolean) {// 此处仅对卡片ID:formId,卡片名:formName和是否为临时卡片:tempFlag进行了持久化let formInfo = {"formName": formName,"tempFlag": tempFlag,"updateCount": 0};try {const storage = await dataStorage.getStorage(DATA_STORAGE_PATH);// put form infoawait storage.put(formId, JSON.stringify(formInfo));console.info(`[EntryFormAbility] storeFormInfo, put form info successfully, formId: ${formId}`);await storage.flush();} catch (err) {console.error(`[EntryFormAbility] failed to storeFormInfo, err: ${JSON.stringify(err)}`);}
}export default class EntryFormAbility extends FormExtension {...onAddForm(want) {console.info('[EntryFormAbility] onAddForm');let formId = want.parameters["ohos.extra.param.key.form_identity"];let formName = want.parameters["ohos.extra.param.key.form_name"];let tempFlag = want.parameters["ohos.extra.param.key.form_temporary"];// 将创建的卡片信息持久化,以便在下次获取/更新该卡片实例时进行使用// 此接口请根据实际情况实现,具体请参考:FormExtAbility Stage模型卡片实例storeFormInfo(formId, formName, tempFlag);let obj = {"title": "titleOnCreate","detail": "detailOnCreate"};let formData = formBindingData.createFormBindingData(obj);return formData;}
}

且需要适配onRemoveForm卡片删除通知接口,在其中实现卡片实例数据的删除。

const DATA_STORAGE_PATH = "/data/storage/el2/base/haps/form_store";
async function deleteFormInfo(formId: string) {try {const storage = await dataStorage.getStorage(DATA_STORAGE_PATH);// del form infoawait storage.delete(formId);console.info(`[EntryFormAbility] deleteFormInfo, del form info successfully, formId: ${formId}`);await storage.flush();} catch (err) {console.error(`[EntryFormAbility] failed to deleteFormInfo, err: ${JSON.stringify(err)}`);}
}...export default class EntryFormAbility extends FormExtension {...onRemoveForm(formId) {console.info('[EntryFormAbility] onRemoveForm');// 删除之前持久化的卡片实例数据// 此接口请根据实际情况实现,具体请参考:FormExtAbility Stage模型卡片实例deleteFormInfo(formId);}
}

具体的持久化方法可以参考应用数据持久化概述。

需要注意的是,卡片使用方在请求卡片时传递给提供方应用的Want数据中存在临时标记字段,表示此次请求的卡片是否为临时卡片:

  • 常态卡片:卡片使用方会持久化的卡片;
  • 临时卡片:卡片使用方不会持久化的卡片;

由于临时卡片的数据具有非持久化的特殊性,某些场景例如卡片服务框架死亡重启,此时临时卡片数据在卡片管理服务中已经删除,且对应的卡片ID不会通知到提供方,所以卡片提供方需要自己负责清理长时间未删除的临时卡片数据。同时对应的卡片使用方可能会将之前请求的临时卡片转换为常态卡片。如果转换成功,卡片提供方也需要对对应的临时卡片ID进行处理,把卡片提供方记录的临时卡片数据转换为常态卡片数据,防止提供方在清理长时间未删除的临时卡片时,把已经转换为常态卡片的临时卡片信息删除,导致卡片信息丢失。

卡片数据交互

当卡片应用需要更新数据时(如触发了定时更新或定点更新),卡片应用获取最新数据,并调用updateForm()接口主动触发卡片的更新。

onUpdateForm(formId) {// 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要重写该方法以支持数据更新console.info('[EntryFormAbility] onUpdateForm');let obj = {"title": "titleOnUpdate","detail": "detailOnUpdate"};let formData = formBindingData.createFormBindingData(obj);// 调用updateForm接口去更新对应的卡片,仅更新入参中携带的数据信息,其他信息保持不变formProvider.updateForm(formId, formData).catch((error) => {console.info('[EntryFormAbility] updateForm, error:' + JSON.stringify(error));});
}

开发卡片页面

开发者可以使用类Web范式(HML+CSS+JSON)开发JS卡片页面。生成如下卡片页面,可以这样配置卡片页面文件:

img

说明

当前仅支持JS扩展的类Web开发范式来实现卡片的UI。

  • HML:使用类Web范式的组件描述卡片的页面信息。

    <div class="container"><stack><div class="container-img"><image src="/common/widget.png" class="bg-img"></image></div><div class="container-inner"><text class="title">{{title}}</text><text class="detail_text" onclick="routerEvent">{{detail}}</text></div></stack>
    </div>
    
  • CSS:HML中类Web范式组件的样式信息。

    .container {flex-direction: column;justify-content: center;align-items: center;
    }.bg-img {flex-shrink: 0;height: 100%;
    }.container-inner {flex-direction: column;justify-content: flex-end;align-items: flex-start;height: 100%;width: 100%;padding: 12px;
    }.title {font-size: 19px;font-weight: bold;color: white;text-overflow: ellipsis;max-lines: 1;
    }.detail_text {font-size: 16px;color: white;opacity: 0.66;text-overflow: ellipsis;max-lines: 1;margin-top: 6px;
    }
    
  • JSON:卡片页面中的数据和事件交互。

    {"data": {"title": "TitleDefault","detail": "TextDefault"},"actions": {"routerEvent": {"action": "router","abilityName": "EntryAbility","params": {"message": "add detail"}}}
    }
    

开发卡片事件

卡片支持为组件设置交互事件(action),包括router事件和message事件,其中router事件用于UIAbility跳转,message事件用于卡片开发人员自定义点击事件。

关键步骤说明如下:

  1. 在HML中为组件设置onclick属性,其值对应到JSON文件的actions字段中。
  2. 设置router事件:
    • action属性值为"router"。
    • abilityName为跳转目标的UIAbility名(支持跳转FA模型的PageAbility组件和Stage模型的UIAbility组件),如目前DevEco Studio创建的Stage模型的UIAbility默认名为EntryAbility。
    • params为传递给跳转目标UIAbility的自定义参数,可以按需填写。其值可以在目标UIAbility启动时的want中的parameters里获取。如Stage模型MainAbility的onCreate生命周期里的入参want的parameters字段下获取到配置的参数。
  3. 设置message事件:
    • action属性值为"message"。
    • params为message事件的用户自定义参数,可以按需填写。其值可以在卡片生命周期函数onFormEvent()中的message里获取。

示例如下。

  • HML文件

    <div class="container"><stack><div class="container-img"><image src="/common/widget.png" class="bg-img"></image></div><div class="container-inner"><text class="title" onclick="routerEvent">{{title}}</text><text class="detail_text" onclick="messageEvent">{{detail}}</text></div></stack>
    </div>
    
  • CSS文件

    .container {flex-direction: column;justify-content: center;align-items: center;
    }.bg-img {flex-shrink: 0;height: 100%;
    }.container-inner {flex-direction: column;justify-content: flex-end;align-items: flex-start;height: 100%;width: 100%;padding: 12px;
    }.title {font-size: 19px;font-weight: bold;color: white;text-overflow: ellipsis;max-lines: 1;
    }.detail_text {font-size: 16px;color: white;opacity: 0.66;text-overflow: ellipsis;max-lines: 1;margin-top: 6px;
    }
    
  • JSON文件

    {"data": {"title": "TitleDefault","detail": "TextDefault"},"actions": {"routerEvent": {"action": "router","abilityName": "EntryAbility","params": {"info": "router info","message": "router message"}},"messageEvent": {"action": "message","params": {"detail": "message detail"}}}
    }
    
  • 在UIAbility中接收router事件并获取参数

    import UIAbility from '@ohos.app.ability.UIAbility'export default class EntryAbility extends UIAbility {onCreate(want, launchParam) {let params = JSON.parse(want.parameters.params);// 获取router事件中传递的info参数if (params.info === "router info") {// do something// console.info("router info:" + params.info)}// 获取router事件中传递的message参数if (params.message === "router message") {// do something// console.info("router message:" + params.message)}}...
    };
    
  • 在FormExtensionAbility中接收message事件并获取参数

    import FormExtension from '@ohos.app.form.FormExtensionAbility';export default class FormAbility extends FormExtension {...onFormEvent(formId, message) {// 获取message事件中传递的detail参数let msg = JSON.parse(message)if (msg.detail === "message detail") {// do something// console.info("message info:" + msg.detail)}}...
    };
    

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/226883.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小型内衣洗衣机什么牌子好?口碑好的小型洗衣机

想必大家都知道&#xff0c;我们的内衣裤、袜子这些衣物对卫生方面的要求是比较的高&#xff0c;毕竟是贴身的衣物&#xff0c;因此是要分开清洗的&#xff0c;而不能够跟我们其他的大件衣服一起放入到大型洗衣机里进行混洗&#xff0c;很多就选择了分开单独的手洗&#xff0c;…

快速上手:Docker环境下的WordPress安装全攻略

在这篇文章中我会手把手地教你在Linux环境下使用Docker安装WordPress及相关应用。最终&#xff0c;你将会拥有一个安全、支持https的网站。别犹豫啦&#xff0c;跟着我一块儿搞起来吧&#xff01; 一、登录服务器 在之前的文章中有提到如何使用ssh命令登录到我们之前在AWS申请…

嵌入式SOC之通用图像处理之OSD文字信息叠加的相关实践记录

机缘巧合 机缘巧合下, 在爱芯元智的xx开发板下进行sdk的开发.由于开发板目前我拿到是当前最新的一版(估计是样品)&#xff0c;暂不公开开发板具体型号信息.以下简称板子 .很多优秀的芯片厂商,都会提供与开发板配套的完善的软件以及完善的技术支持(FAE)&#xff0c;突然觉得爱芯…

Kubernetes 的用法和解析(K8S 日志方案) -- 8

一、统一日志管理的整体方案 通过应用和系统日志可以了解Kubernetes集群内所发生的事情&#xff0c;对于调试问题和监视集群活动来说日志非常有用。对于大部分的应用来说&#xff0c;都会具有某种日志机制。因此&#xff0c;大多数容器引擎同样被设计成支持某种日志机制。 对…

android studio 将含有jni c++ 的library项目封装成jar并调用

请参考博客&#xff1a;android studio 4.1.1 将library项目封装成aar 并调用_android studio 4.1 aar release-CSDN博客 一 . 简单叙述 android studio 中可以创建Module 的两种属性&#xff0c;可以在build.gradle 中查看&#xff1a; 1. application属性&#xff1a;可以独…

前后端分离nodejs+vue医院预约挂号系统6nrhh

医院预约挂号系统主要有管理员、用户和医生三个功能模块。以下将对这三个功能的作用进行详细的剖析。 运行软件:vscode 前端nodejsvueElementUi 语言 node.js 框架&#xff1a;Express/koa 前端:Vue.js 数据库&#xff1a;mysql 开发软件&#xff1a;VScode/webstorm/hbuiderx均…

计算机视觉技术-锚框

目标检测算法通常会在输入图像中采样大量的区域&#xff0c;然后判断这些区域中是否包含我们感兴趣的目标&#xff0c;并调整区域边界从而更准确地预测目标的真实边界框&#xff08;ground-truth bounding box&#xff09;。 不同的模型使用的区域采样方法可能不同。 这里我们介…

图像分割实战-系列教程1:语义分割与实例分割概述

1、图像分割任务概述 1.1 图像分割 分割任务就是在原始图像中逐像素的找到你需要的轮廓 如图分别是&#xff08;物体检测&#xff09;与&#xff08;图像分割&#xff09;两个任务的效果对比&#xff0c;实际上会比检测任务要稍微麻烦一些&#xff0c;将图像会分为几个区域把…

学习笔记:R语言基础

文章目录 一、R语言简介二、选择R的原因三、R基本数据对象&#xff08;一&#xff09;向量&#xff08;二&#xff09;矩阵&#xff08;三&#xff09;数组&#xff08;四&#xff09;因子&#xff08;五&#xff09;列表&#xff08;六&#xff09;数据框&#xff08;七&#…

uni-app condition启动模式配置

锋哥原创的uni-app视频教程&#xff1a; 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中...共计23条视频&#xff0c;包括&#xff1a;第1讲 uni…

DM、Oracle、GaussDB、Kingbase8(人大金仓数据库)和HIVE给列增加注释

DM数据库给列增加注释 1、创建表 CREATE TABLE test222 ( id int NOT NULL PRIMARY KEY, name varchar(1000) DEFAULT NULL, email varchar(1000) DEFAULT NULL, phone varchar(1000) DEFAULT NULL ) 2、给列添加注释 comment on column TEST222.NAME is 这是一个列注释; 例如…

数字身份验证:跨境电商如何应对账户安全挑战?

在数字化时代&#xff0c;随着跨境电商的蓬勃发展&#xff0c;账户安全问题逐渐成为行业和消费者关注的焦点。随着网络犯罪日益猖獗&#xff0c;用户的数字身份安全面临着更加复杂的威胁。本文将深入探讨数字身份验证在跨境电商中的重要性&#xff0c;并探讨各种创新技术和策略…

Android MVC 写法

前言 Model&#xff1a;负责数据逻辑 View&#xff1a;负责视图逻辑 Controller&#xff1a;负责业务逻辑 持有关系&#xff1a; 1、View 持有 Controller 2、Controller 持有 Model 3、Model 持有 View 辅助工具&#xff1a;ViewBinding 执行流程&#xff1a;View >…

Windows系统配置pytorch环境,Jupyter notebook编辑器安装使用(深度学习本地篇)

如今现在好一点的笔记本都自带英伟达独立显卡&#xff0c;对于一些简单的深度学习项目&#xff0c;是不需要连接服务器的&#xff0c;甚至数据量不大的话&#xff0c;cpu也足够进行训练学习。我把电脑上一些以前的笔记整理一下&#xff0c;记录起来&#xff0c;方便自己35岁事业…

python/selenium/jenkins整合

1、新建python项目&#xff0c;专门写selenium代码&#xff0c;建议用pytest框架写。 2、把代码上传到代码库中。 3、环境配置&#xff1a; 3.1 在跑jenkins的机器上配置好python环境&#xff0c;需要python --version能在任何地方运行&#xff08;配置好系统环境变量&#…

Idea配置热部署

Idea配置热部署 一、概念 热部署就是正在运行状态的应用&#xff0c;修改了他的源码之后&#xff0c;在不重新启动的情况下能够自动把增量内容编译并部署到服务器上&#xff0c;使得修改立即生效。热部署为了解决的问题有两个&#xff0c; 一是在开发的时候&#xff0c;修改代…

【Python排序算法系列】—— 选择排序

​ &#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 &#x1f4ab;个人格言:"没有罗马,那就自己创造罗马~" 目录 选择排序 过程演示&#xff1a; 选择排序实现代码&#xff1a; 分析选择排序&#xff1a…

nodejs+vue+微信小程序+python+PHP的林业信息管理系统的设计与实现-计算机毕业设计推荐

本文先充分调查林业信息管理系统的需求分析&#xff0c;深入剖析系统应该具有的功能&#xff0c;并设计完善的数据库。利用成熟的开发技术完成编码工作&#xff0c;林业信息管理系统可以为林业局领导提供业务管理功能&#xff0c;林业局领导也就是系统的管理员&#xff0c;具有…

深入ArkUI:深入实战组件text和text input

文章目录 Text组件介绍Text组件的属性方法Text:文本显示组件4.3TextInput组件实战案例:图片宽度控制页面本文总结要点回顾在今天的课程中,我们将深入学习ArkUI提供的基础组件,着重探讨text和text input两个组件。 Text组件介绍 Text组件是一个用于显示文本的组件,其主要作…

重新认识Word——自动目录

重新认识Word——自动目录 自动插入目录要点大纲级别 自定义目录格式给图表插入目录致谢和参考文献没有在目录之中一些目录的问题目录中有“目录”二字一份文档&#xff0c;两份目录 之前我们对文本内容的编辑有了一个大概的了解&#xff0c;接下来我们来了解一下&#xff0c;W…