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

卡片里放图片?用 memory:// 协议才是正确打开方式

文章目录卡片图片的限制项目结构卡片 UI用 memory:// 显示图片FormAbility下载图片 → 写入共享内存 → 推送更新显示本地图片无需下载memory:// 协议原理关键注意事项写在最后卡片里显示图片这件事比我想象的要麻烦一点。卡片跑在独立的渲染进程里没法直接访问网络也没法直接读你应用的文件路径。想显示动态图片要走一个专门的内存共享机制——memory://协议。今天把这套图片更新方案从头到尾讲清楚。卡片图片的限制先说为什么不能直接用Image(https://...)或者Image(/data/...)卡片渲染进程是沙盒卡片 UI 代码跑在一个受限进程里没有网络权限也读不了宿主应用的私有目录Image 组件有限制卡片里的Image只支持应用包内的资源$r()和memory://协议不支持 HTTP URL数据传递有大小限制卡片数据通过FormBindingData传递不能直接传二进制图片数据官方给的解决方案是在FormExtensionAbility里下载图片并写入共享内存然后把共享内存的 key文件名通过updateForm传给卡片 UI卡片 UI 用memory://key访问图片。项目结构StageServiceWidgetCards/ └── entry/src/main/ets/ ├── widgetimageupdate/ │ ├── pages/ │ │ └── WidgetImageUpdateCard.ets ← 卡片 UI │ └── widgetimageabilify/ │ └── WidgetImageFormAbility.ets ← 卡片 Ability └── pages/ └── Index.ets ← 主页面卡片 UI用 memory:// 显示图片// entry/src/main/ets/widgetimageupdate/pages/WidgetImageUpdateCard.etsletstorageWidgetImageUpdatenewLocalStorage();Entry(storageWidgetImageUpdate)Componentstruct WidgetImageUpdateCard{LocalStorageProp(text)text:ResourceStr$r(app.string.loading);// loaded 标志true 时显示共享内存图片false 时显示默认占位图LocalStorageProp(loaded)loaded:booleanfalse;// imgName 是共享内存里图片的 key由 FormAbility 传入LocalStorageProp(imgName)imgName:ResourceStr$r(app.string.imgName);build(){Column(){Column(){Text(this.text).fontColor(#FFFFFF).opacity(0.9).fontSize(12).textOverflow({overflow:TextOverflow.Ellipsis}).maxLines(1).margin({top:8%,left:10%})}.width(100%).height(50%).alignItems(HorizontalAlign.Start)Row(){Button(){Text(刷新图片).fontColor(#45A6F4).fontSize(12)}.width(120).height(32).margin({top:30%,bottom:10%}).backgroundColor(#FFFFFF).borderRadius(16).onClick((){// 发送 message 事件让 FormAbility 去下载新图片postCardAction(this,{action:message,params:{info:refreshImage// FormAbility 会识别这个参数}});})}.width(100%).height(40%).justifyContent(FlexAlign.Center)}.width(100%).height(100%)// 核心loadedtrue 时用 memory:// 协议否则显示本地占位图.backgroundImage(this.loaded?memory://this.imgName// memory:// imgName 从共享内存读图片:$r(app.media.ImageDisp)// 未加载时显示默认图).backgroundImageSize(ImageSize.Cover)}}FormAbility下载图片 → 写入共享内存 → 推送更新// entry/src/main/ets/widgetimageupdate/widgetimageabilify/WidgetImageFormAbility.etsimport{formBindingData,FormExtensionAbility,formProvider}fromkit.FormKit;import{Want}fromkit.AbilityKit;import{BusinessError}fromkit.BasicServicesKit;import{http}fromkit.NetworkKit;import{image}fromkit.ImageKit;constTAGWidgetImageFormAbility;exportdefaultclassWidgetImageFormAbilityextendsFormExtensionAbility{onAddForm(want:Want):formBindingData.FormBindingData{// 卡片创建时先显示本地占位图状态constformData:Recordstring,boolean|string{loaded:false,text:图片加载中...};returnformBindingData.createFormBindingData(formData);}onFormEvent(formId:string,message:string):void{// 收到卡片的 message 事件constmsg:Recordstring,stringJSON.parse(message);if(msg.inforefreshImage){// 下载网络图片并更新到卡片this.downloadAndUpdateImage(formId);}}privateasyncdownloadAndUpdateImage(formId:string):Promisevoid{constimageUrlhttps://example.com/sample.png;// 替换为实际图片URLtry{// 1. 创建 HTTP 实例下载图片consthttpRequesthttp.createHttp();constresponseawaithttpRequest.request(imageUrl,{method:http.RequestMethod.GET,expectDataType:http.HttpDataType.ARRAY_BUFFER,connectTimeout:10000,readTimeout:10000});httpRequest.destroy();// 2. 将 ArrayBuffer 转成 PixelMapconstimageSourceimage.createImageSource(response.resultasArrayBuffer);constpixelMapawaitimageSource.createPixelMap({editable:false,desiredSize:{width:200,height:200}});// 3. 构造带图片的 FormBindingData// imgName 是共享内存的 key卡片用 memory://imgName 访问constimgNamedownloaded_image;constformData:Recordstring,boolean|string|image.PixelMap{loaded:true,// 通知 UI 图片已加载完成imgName:imgName,// 图片的 keytext:图片更新成功,[imgName]:pixelMap// 以 key 为属性名存放 PixelMap};constformInfoformBindingData.createFormBindingData(formData);// 4. 推送数据卡片自动显示新图片awaitformProvider.updateForm(formId,formInfo);console.info(${TAG}: 图片更新成功);}catch(error){consterrerrorasBusinessError;console.error(${TAG}: 图片下载失败${err.code}:${err.message});// 失败时推送错误状态consterrorData:Recordstring,boolean|string{loaded:false,text:图片加载失败请重试};awaitformProvider.updateForm(formId,formBindingData.createFormBindingData(errorData));}}}显示本地图片无需下载如果只是想更新本地的应用资源图片也可以不走网络// FormAbility 里直接用 $r 引用应用内图片onUpdateForm(formId:string):void{// 用 PixelMap 方式传递应用包内图片constcontextthis.context;// 方式一读取 rawfile 目录里的图片context.resourceManager.getRawFileContent(images/banner.png).then((data:Uint8Array){constimageSourceimage.createImageSource(data.bufferasArrayBuffer);returnimageSource.createPixelMap();}).then((pixelMap:image.PixelMap){constimgNamelocal_image;constformData:Recordstring,boolean|string|image.PixelMap{loaded:true,imgName:imgName,text:本地图片,[imgName]:pixelMap};returnformProvider.updateForm(formId,formBindingData.createFormBindingData(formData));});}memory:// 协议原理关键注意事项1.memory://只能在卡片里用普通应用页面的Image组件不认memory://这个协议是卡片渲染引擎专属的。2. PixelMap 要作为属性值传入 FormBindingData这是最容易搞错的地方。imgName是图片的 keyformData[imgName] pixelMap把 PixelMap 对象放进去memory://imgName才能找到这个图片。// 正确写法constimgNamemyImage;constformData{imgName:imgName,// 告诉 UI 用哪个 key[imgName]:pixelMap// 以这个 key 存放 PixelMap};// 错误写法少了 PixelMap 数据constformData{imgName:imgName// UI 读到了 key但内存里没有图显示空白};3. 图片不会自动清理共享内存里的图片在卡片刷新后不会立即释放多次更新后可能积累很多。生产环境里要注意图片大小建议不超过 1MB。4. 网络请求要放在 onFormEvent 里FormExtensionAbility只有 5 秒存活时间不要在onAddForm里做耗时的网络请求最好在onFormEvent里按需下载。写在最后卡片图片这块确实绕核心逻辑是FormAbility 当中间人下好图片转成 PixelMap 塞进共享内存卡片 UI 用memory://协议取图。搞清楚这个模式之后写起来其实不难就是 FormBindingData 里那个[imgName]: pixelMap的写法比较反直觉记住就好。

相关文章:

卡片里放图片?用 memory:// 协议才是正确打开方式

文章目录卡片图片的限制项目结构卡片 UI:用 memory:// 显示图片FormAbility:下载图片 → 写入共享内存 → 推送更新显示本地图片(无需下载)memory:// 协议原理关键注意事项写在最后卡片里显示图片这件事比我想象的要麻烦一点。卡片…...

B站视频下载终极指南:5步轻松掌握BilibiliDown完整教程

B站视频下载终极指南:5步轻松掌握BilibiliDown完整教程 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/…...

Linux主机资产标识实战指南

Linux主机资产标识实战指南本文面向具备一定 Linux 基础的技术人员,围绕主机资产标识展开,重点讨论主机命名、标签规范和资产映射。在中级运维和系统管理工作中,这类主题常常与配置变更、资源状态、权限边界、自动化任务和业务影响交织在一起…...

避开这3个坑,你的STM32F103+LoRa+阿里云项目才能跑得稳

STM32F103LoRa阿里云物联网项目稳定性优化实战指南 在物联网设备开发中,稳定性往往是区分业余原型与工业级产品的关键分水岭。许多开发者能够快速搭建起STM32F103与LoRa模块的基础通信框架,并实现阿里云物联网平台的数据上传,却在长期运行中频…...

基于Vue3+TypeScript的ChatGPT风格前端界面集成实战

1. 项目概述与核心价值最近在折腾一个个人项目,想给一个静态网站加上智能对话的能力,让访客能随时问点问题。一开始想自己从零搭建,但考虑到前后端、AI接口、实时通信这些环节,工作量着实不小。后来在GitHub上逛的时候&#xff0c…...

WRF-CHEM模拟翻车?可能是你的namelist.chem没设对(附MEIC数据实战配置清单)

WRF-CHEM模拟异常排查指南:MEIC数据与namelist.chem的深度适配 当WRF-CHEM模拟结果出现异常时,很多用户会第一时间怀疑MEIC数据处理环节的问题,但实际上,namelist.chem参数与MEIC特性的匹配度才是更隐蔽的关键因素。本文将带您深入…...

Claude技能库开发指南:工具调用原理与模块化实践

1. 项目概述:一个为Claude模型量身定制的技能库最近在探索如何让Claude这类大型语言模型更好地融入我的日常工作流时,我遇到了一个非常有意思的项目——DhanushNehru/claude-skills。简单来说,这是一个专门为Anthropic的Claude模型设计的“技…...

LabVIEW PC端软件开发:架构设计、性能优化与工程化实践

1. 项目概述:为什么选择在PC上深耕LabVIEW开发?当大家谈论起LabVIEW,很多人的第一印象可能还停留在它与各种数据采集卡、PLC、嵌入式硬件绑定的场景里。作为一个在这个图形化编程环境里摸爬滚打了十多年的老工程师,我想说&#xf…...

Consul-K8s实战:Kubernetes与Consul服务网格的无缝集成指南

1. 项目概述:当Consul遇见Kubernetes如果你正在Kubernetes集群里管理微服务,并且已经听说过或者正在使用HashiCorp Consul来做服务发现和配置管理,那么hashicorp/consul-k8s这个项目绝对是你绕不开的工具。简单来说,它不是一个独立…...

实测Taotoken多模型聚合调用的响应延迟与稳定性观感

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 实测Taotoken多模型聚合调用的响应延迟与稳定性观感 在项目开发中,我们常常需要接入不同的大模型来满足多样化的需求。…...

为OpenClaw配置Taotoken作为其AI模型供应商

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 为OpenClaw配置Taotoken作为其AI模型供应商 基础教程类,指导使用OpenClaw这类Agent工具的开发者,如何将其后…...

基于ARM9核心板的工业双CAN网关开发实战:从硬件选型到软件架构

1. 项目概述与核心价值最近在做一个工业网关项目,客户要求设备必须支持双路CAN总线,用于同时连接现场的执行器和上位机监控系统。时间紧,任务重,自己从头设计硬件、画板、调试驱动,周期太长,风险也高。这时…...

XUnity Auto Translator:3分钟为Unity游戏添加多语言支持的终极解决方案

XUnity Auto Translator:3分钟为Unity游戏添加多语言支持的终极解决方案 【免费下载链接】XUnity.AutoTranslator 项目地址: https://gitcode.com/gh_mirrors/xu/XUnity.AutoTranslator 你是否曾因语言障碍而放弃心爱的Unity游戏?或者作为开发者…...

Linux驱动调试利器:debugfs接口设计与实现详解

1. 项目概述:为什么我们需要debugfs?在Linux内核驱动的开发与调试过程中,我们常常面临一个核心痛点:如何在不重启系统、不重新编译驱动、甚至不借助复杂外部工具的情况下,实时地窥探驱动内部的状态、修改关键参数&…...

深度学习立体匹配:从MC-CNN架构解析到工程实践优化

1. 项目概述:从传统到深度,立体匹配的范式革新在计算机视觉领域,立体匹配是一个经典且核心的问题,它的目标是从一对经过校正的左右图像中,为每个像素找到其在另一幅图像中的对应点,从而计算出场景的深度信息…...

frp-panel:基于Web的图形化管理面板,让内网穿透配置更高效

1. 项目概述:一个为内网穿透工具打造的管理面板如果你用过 frp,大概率会和我有同样的感受:它的功能强大、性能稳定,是解决内网服务暴露、远程访问等问题的利器。但它的配置方式——编辑一个文本格式的.toml或.ini文件,…...

手把手教你学Simulink——新能源并网逆变器的最大功率点跟踪(MPPT)与并网联合仿真

目录 手把手教你学Simulink——新能源并网逆变器的最大功率点跟踪(MPPT)与并网联合仿真 一、背景与挑战 1.1 为什么新能源并网离不开 MPPT? 1.2 核心痛点与设计目标 二、系统架构与核心控制推导 2.1 整体架构:DC 级联的“能量接力棒” 2.2 核心数学推导:看穿 MPPT 的…...

Composer依赖管理可视化:saketsarin/composer-web工具详解与实践指南

1. 项目概述:一个为Composer量身定制的Web管理界面如果你是一名PHP开发者,那么对Composer一定不会陌生。它是PHP生态的基石,一个强大的依赖管理工具,让我们能够通过一条简单的命令,将成千上万的第三方库引入到自己的项…...

在 Simulink 中实现并网双向 DC/AC 逆变器的无功补偿(SVG)功能仿真

目录 🛠️ 第一步:系统架构设计与模块搭建 ⚙️ 第二步:SVG 核心控制策略设计(双闭环控制) 📊 第三步:仿真运行与结果分析 手把手教你在 Simulink 中实现并网双向 DC/AC 逆变器的无功补偿(SVG)功能仿真。 在现代电力系统中,并网逆变器(如光伏、储能逆变器)不…...

基于STM32的物联网健康监测平台:硬件设计、驱动开发与系统整合

1. 项目概述:一个面向物联网健康监测的STM32开发平台最近在整理手头的项目资料,翻出来一块几年前自己设计并打样的STM32开发板。这块板子当初的定位很明确,就是做一个功能集成度高的“物联网健康监测终端”原型平台。它不是那种追求极致性能的…...

U-boot QSPI驱动移植实战:从Flash适配到启动验证全解析

1. 项目概述:为什么U-boot的QSPI驱动移植是个“硬骨头”?在嵌入式系统开发,尤其是基于ARM Cortex-A系列处理器的工控、车载或高端物联网设备中,U-boot作为系统启动的“第一棒”至关重要。而QSPI(Quad SPI)接…...

RK3588 PCIe拆分技术:从原理到实战的嵌入式扩展方案

1. 项目概述:为什么RK3588的PCIE拆分如此重要?如果你正在基于瑞芯微RK3588这颗旗舰级SoC开发产品,无论是边缘计算盒子、NAS、工业网关还是高性能平板,那么PCIE总线的灵活运用绝对是你绕不开的课题。RK3588提供了多达4个PCIE 3.0控…...

保利商旅诺雅品牌首作,长沙保利橘洲诺雅酒店开业

美通社消息:5月15日,由保利发展湖南公司投资兴建、保利商旅产业发展有限公司运营管理的豪华城市度假品牌——诺雅(ORYARD)首店:长沙保利橘洲诺雅酒店,于湘江之畔正式盛大开业。该项目自2026年2月试营业以来,历经数月的…...

树莓派5 vs 树莓派4:从硬件架构到应用场景的全面对比与实战指南

1. 项目概述:为什么我们需要重新审视树莓派5?如果你和我一样,从树莓派2、3、4一路用过来,每次新版本发布都像是一次“挤牙膏”式的升级,那么树莓派5的到来,绝对会打破你的固有印象。它不再仅仅是“更快一点…...

国产碳化硅MOSFET在通讯电源PFC中的应用与实战解析

1. 项目概述:当通讯电源遇上国产碳化硅MOSFET最近在做一个通讯电源的PFC(功率因数校正)项目,客户对效率、功率密度和可靠性提出了近乎苛刻的要求。传统的硅基MOSFET方案,在追求更高开关频率以减小磁性元件体积时&#…...

3分钟极速激活:KMS智能激活工具让你的Windows和Office永久免费使用

3分钟极速激活:KMS智能激活工具让你的Windows和Office永久免费使用 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows系统频繁弹出激活提示而烦恼吗?Office文…...

鸿蒙 HarmonyOS 6.0 页面构建实践:跨端数字图书馆界面实现

鸿蒙 HarmonyOS 6.0 页面构建实践:跨端数字图书馆界面实现 前言 随着移动互联网和物联网的高速发展,跨端应用开发已成为现代软件开发的重要趋势。开发者不仅需要在手机端提供流畅的用户体验,还需要兼顾平板、电视等多终端的适配问题。在这样的…...

通过环境变量管理多个 Taotoken API Key 以实现访问控制

🚀 告别海外账号与网络限制!稳定直连全球优质大模型,限时半价接入中。 👉 点击领取海量免费额度 通过环境变量管理多个 Taotoken API Key 以实现访问控制 在开发过程中,我们常常需要为不同的应用、不同的环境&#xf…...

在线水印怎么去除?2026年最新在线水印去除方法与工具推荐

图片、视频上的水印是版权保护的常见方式,但在内容创作、素材整理或个人使用时,有时需要移除这些标记。在线水印去除工具因为无需下载安装、跨平台兼容而成为不少人的选择。本文汇总了2026年实用的在线水印去除方法和工具推荐,帮你快速找到适…...

语义分割模型库选型指南:除了segmentation_models_pytorch,还有哪些宝藏库?附113个编码器实战对比

语义分割模型库深度选型指南:从SMP到工业级解决方案全景解析 当面对一个全新的语义分割项目时,工程师们往往会在众多开源模型库前陷入选择困难。本文将带您深入剖析主流语义分割工具库的技术特性、适用场景与实战表现,帮助您做出精准的技术决…...