HarmonyOS Next 实战卡片开发 03

HarmonyOS Next 实战卡片开发 03

在前面两张,我们基本掌握了卡片的使用流程,本章节就通过一个实战来加强对卡片使用的理解。

要完成的案例

image-20241024175411585


PixPin_2024-10-24_17-54-18

新建项目和新建服务卡片

image-20241031111045865


image-20241031111130741

设置沉浸式

entry/src/main/ets/entryability/EntryAbility.ets

image-20241031111326923

首页显示轮播图数据

PixPin_2024-10-31_11-27-05

1. 申请网络权限

entry/src/main/module.json5

image-20241031112238553

2. 新建工具文件 /utils/index.ets

entry/src/main/ets/utils/index.ets

export const swiperInit = () => {AppStorage.setOrCreate("swiperList", ["https://env-00jxhf99mujs.normal.cloudstatic.cn/card/1.webp?expire_at=1729734506&er_sign=e51cb3b4f4b28cb2da96fd53701eaa69","https://env-00jxhf99mujs.normal.cloudstatic.cn/card/2.webp?expire_at=1729734857&er_sign=b2ffd42585568a094b9ecfb7995a9763","https://env-00jxhf99mujs.normal.cloudstatic.cn/card/3.webp?expire_at=1729734870&er_sign=50d5f210191c113782958dfd6681cd2d",])AppStorage.setOrCreate("activeIndex", 0)
}

3. 初始化

entry/src/main/ets/entryability/EntryAbility.ets

image-20241031111803516

4. 页面中使用

entry/src/main/ets/pages/Index.ets


@Entry
@Component
struct Index {@StorageProp("swiperList")swiperList: string[] = []@StorageLink("activeIndex")activeIndex: number = 0build() {Column() {Swiper() {ForEach(this.swiperList, (img: string) => {Image(img).width("80%")})}.loop(true).autoPlay(true).interval(3000).onChange(index => this.activeIndex = index)}.height('100%').width('100%').justifyContent(FlexAlign.Center).backgroundImage(this.swiperList[this.activeIndex]).backgroundBlurStyle(BlurStyle.Thin).backgroundImageSize(ImageSize.Cover).animation({ duration: 500 })}
}

5. 效果

PixPin_2024-10-31_11-27-05

创建卡片时,获取卡片id

PixPin_2024-10-31_13-06-50

image-20241031222230532

1. 获取和返回卡片id

这里解析下为什么要返回id给卡片组件,因为后期卡片想要向应用通信时,应用响应数据要根据卡片id来响应。

另外 formExtensionAbility进程不能常驻后台,即在卡片生命周期回调函数中无法处理长时间的任务,在生命周期调度完成后会继续存在10秒,如10秒内没有新的

生命周期回调触发则进程自动退出。针对可能需要10秒以上才能完成的业务逻辑,建议拉起主应用进行处理,处理完成后使用updateForm通知卡片进行刷新

entry/src/main/ets/entryformability/EntryFormAbility.ets

  onAddForm(want: Want) {class FormData {// 获取卡片idformId: string = want.parameters!['ohos.extra.param.key.form_identity'].toString();}let formData = new FormData()return formBindingData.createFormBindingData(formData);}

2. 接受和显示卡片id

entry/src/main/ets/widget/pages/WidgetCard.ets

const localStorage = new LocalStorage()@Entry(localStorage)
@Component
struct WidgetCard {@LocalStorageProp("formId")formId: string = ""build() {Row() {Text(this.formId)}.width("100%").height("100%").justifyContent(FlexAlign.Center).padding(10)}
}

3. 效果

PixPin_2024-10-31_13-06-50

记录卡片id,持久化存储

image-20241031223836426

主要流程如下:

  1. 封装持久化存储卡片id的工具类
  2. 初始化卡片id工具类
  3. 卡片主动上传卡片id
  4. 应用Aibility接收卡片id
  5. 接收卡片id并且持久化
  6. 移除卡片时,删除卡片id

1. 封装持久化存储卡片id的工具类

此时接收到卡片id后,需要将卡片id持久化存储,避免重新打卡手机时,无法联系到已经创建的卡片

entry/src/main/ets/utils/index.ets

export class FormIdStore {static key: string = "wsy_collect"static dataPreferences: preferences.Preferences | null = null;static context: Context | null = null//  初始化static init(context?: Context) {if (!FormIdStore.dataPreferences) {if (context) {FormIdStore.context = context}FormIdStore.dataPreferences =preferences.getPreferencesSync(FormIdStore.context || getContext(), { name: FormIdStore.key })}}//  获取卡片id 数组static getList() {FormIdStore.init()const str = FormIdStore.dataPreferences?.getSync(FormIdStore.key, '[]')const list = JSON.parse(str as string) as string[]console.log("list卡片", list)return list}// 新增卡片数组static async set(item: string) {FormIdStore.init()const list = FormIdStore.getList()if (!list.includes(item)) {list.push(item)FormIdStore.dataPreferences?.putSync(FormIdStore.key, JSON.stringify(list))await FormIdStore.dataPreferences?.flush()}}// 删除元素static async remove(item: string) {FormIdStore.init()const list = FormIdStore.getList()const index = list.indexOf(item)if (index !== -1) {list.splice(index, 1)FormIdStore.dataPreferences?.putSync(FormIdStore.key, JSON.stringify(list))await FormIdStore.dataPreferences?.flush()}}
}

2. 初始化卡片id工具类

  1. onCreate中初始化

    entry/src/main/ets/entryability/EntryAbility.ets

      onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {FormIdStore.init(this.context)
    
  2. onAddForm中初始化

    onAddForm(want: Want) {FormIdStore.init(this.context)
    

3. 卡片主动上传卡片id

利用watch监听器来触发上传

entry/src/main/ets/widget/pages/WidgetCard.ets

const localStorage = new LocalStorage()@Entry(localStorage)
@Component
struct WidgetCard {@LocalStorageProp("formId")@Watch("postData")formId: string = ""// 上传卡片idpostData() {postCardAction(this, {action: 'call',abilityName: 'EntryAbility',params: {method: 'createCard',formId: this.formId}});}build() {Row() {Text(this.formId)}.width("100%").height("100%").justifyContent(FlexAlign.Center).padding(10)}
}

4. 应用Aibility接收卡片id

entry/src/main/ets/entryability/EntryAbility.ets

// callee中要求返回的数据类型
class MyPara implements rpc.Parcelable {marshalling(dataOut: rpc.MessageSequence): boolean {return true}unmarshalling(dataIn: rpc.MessageSequence): boolean {return true}
}onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {FormIdStore.init(this.context)// 监听事件this.callee.on("createCard", (data: rpc.MessageSequence) => {// 接收idconst formId = (JSON.parse(data.readString() as string) as Record<string, string>).formIdreturn new MyPara()})}

5. 接收卡片id并且持久化

  1. 开启后台运行权限 “ohos.permission.KEEP_BACKGROUND_RUNNING”

    entry/src/main/module.json5

        "requestPermissions": [{"name": "ohos.permission.INTERNET"},{"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"}],
    
  2. 持久化

     onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {FormIdStore.init(this.context)// 监听事件this.callee.on("createCard", (data: rpc.MessageSequence) => {// 接收idconst formId = (JSON.parse(data.readString() as string) as Record<string, string>).formId// 2 持久化FormIdStore.set(formId)return new MyPara()})}

6. 移除卡片时,删除卡片id

entry/src/main/ets/entryformability/EntryFormAbility.ets

  onRemoveForm(formId: string) {FormIdStore.remove(formId)}

封装下载图片工具类

将下载图片和拼接卡片需要格式的代码封装到文件中 该工具类可以同时下载多张图片,使用了Promise.all 来统一接收结果

entry/src/main/ets/utils/CardDonwLoad.ets

1. 封装的工具说明

interface IDownFile {fileName: stringimageFd: number
}// 卡片显示 需要的数据结构
export class FormDataClass {// 卡片需要显示图片场景, 必填字段(formImages 不可缺省或改名), fileName 对应 fdformImages: Record<string, number>constructor(formImages: Record<string, number>) {this.formImages = formImages}
}export class CardDownLoad {context: Context | nullthen: Function | null = nullimgFds: number[] = []constructor(context: Context) {this.context = context}// 下载单张图片async downLoadImage(netFile: string) {}// 下载一组图片async downLoadImages(netFiles: string[]) {}// 私有下载网络图片的方法private async _down(netFile: string) {}// 手动关闭文件async closeFile() {this.imgFds.forEach(fd => fileIo.closeSync(fd))this.imgFds = []}
}

2. 封装的实现

import { http } from '@kit.NetworkKit';
import { fileIo } from '@kit.CoreFileKit';interface IDownFile {fileName: stringimageFd: number
}// 卡片显示 需要的数据结构
export class FormDataClass {// 卡片需要显示图片场景, 必填字段(formImages 不可缺省或改名), fileName 对应 fdformImages: Record<string, number>constructor(formImages: Record<string, number>) {this.formImages = formImages}
}export class CardDownLoad {context: Context | nullthen: Function | null = nullimgFds: number[] = []constructor(context: Context) {this.context = context}// 下载单张图片async downLoadImage(netFile: string) {const obj = await this._down(netFile)let imgMap: Record<string, number> = {};imgMap[obj.fileName] = obj.imageFdif (!this.imgFds.includes(obj.imageFd)) {this.imgFds.includes(obj.imageFd)}return new FormDataClass(imgMap)}// 下载一组图片async downLoadImages(netFiles: string[]) {let imgMap: Record<string, number> = {};const promiseAll = netFiles.map(url => {const ret = this._down(url)return ret})const resList = await Promise.all(promiseAll)resList.forEach(v => {imgMap[v.fileName] = v.imageFdif (!this.imgFds.includes(v.imageFd)) {this.imgFds.includes(v.imageFd)}})return new FormDataClass(imgMap)// return resList.map(v => `memory://${v.fileName}`)}// 私有下载网络图片的方法private async _down(netFile: string) {let tempDir = this.context!.getApplicationContext().tempDir;let fileName = 'file' + Date.now();let tmpFile = tempDir + '/' + fileName;let httpRequest = http.createHttp()let data = await httpRequest.request(netFile);if (data?.responseCode == http.ResponseCode.OK) {let imgFile = fileIo.openSync(tmpFile, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);await fileIo.write(imgFile.fd, data.result as ArrayBuffer);const obj: IDownFile = {fileName,imageFd: imgFile.fd}// setTimeout(() => {// }, 0)// fileIo.close(imgFile);httpRequest.destroy();return obj} else {httpRequest.destroy();return Promise.reject(null)}}// 手动关闭文件async closeFile() {this.imgFds.forEach(fd => fileIo.closeSync(fd))this.imgFds = []}
}

卡片发起通知,获取网络图片

PixPin_2024-10-31_20-52-33

image-20241031224019379

  1. 准备好卡片代码,用来接收返回的网络图片数据
  2. 应用Ability接收卡片通知,下载网络图片,并且返回给卡片

1. 准备好卡片代码,用来接收返回的网络图片数据

const localStorage = new LocalStorage()@Entry(localStorage)
@Component
struct WidgetCard {// 用来显示图片的数组@LocalStorageProp("imgNames")imgNames: string[] = []// 卡片id@LocalStorageProp("formId")@Watch("postData")formId: string = ""// 当前显示的大图 -  和 应用-首页保持同步@LocalStorageProp("activeIndex")activeIndex: number = 0postData() {postCardAction(this, {action: 'call',abilityName: 'EntryAbility',params: {method: 'createCard',formId: this.formId}});}build() {Row() {ForEach(this.imgNames, (url: string, index: number) => {Image(url).border({ width: 1 }).layoutWeight(this.activeIndex === index ? 2 : 1).height(this.activeIndex === index ? "90%" : "60%").borderRadius(this.activeIndex === index ? 12 : 5).animation({ duration: 300 })})}.width("100%").height("100%").justifyContent(FlexAlign.Center).padding(10).backgroundImage(this.imgNames[this.activeIndex]).backgroundBlurStyle(BlurStyle.Thin).backgroundImageSize(ImageSize.Cover).animation({ duration: 300 })}
}

2. 应用Ability接收卡片通知,下载网络图片,并且返回给卡片

entry/src/main/ets/entryability/EntryAbility.ets

// callee中要求返回的数据类型class MyPara implements rpc.Parcelable {marshalling(dataOut: rpc.MessageSequence): boolean {return true}unmarshalling(dataIn: rpc.MessageSequence): boolean {return true}
}export default class EntryAbility extends UIAbility {onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {// 监听事件this.callee.on("createCard", (data: rpc.MessageSequence) => {// 接收idconst formId = (JSON.parse(data.readString() as string) as Record<string, string>).formId// 持久化FormIdStore.set(formId)class FormData {imgName?: string[] = []activeIndex?: number = AppStorage.get("activeIndex")!}const formInfo = formBindingData.createFormBindingData(new FormData)// 先响应空数据 等待网络图片下载完毕后,再响应网络图片数据formProvider.updateForm(formId, formInfo)const cardDownLoad = new CardDownLoad(this.context)cardDownLoad.downLoadImages(AppStorage.get("swiperList") as string[]).then(ret => {const urls = Object.keys(ret.formImages).map(v => `memory://${v}`)// 返回卡片数组class CimgNames {imgNames: string[] = urlsformImages: Record<string, number> = ret.formImages}const formInfo = formBindingData.createFormBindingData(new CimgNames)formProvider.updateForm(formId, formInfo)//   关闭文件cardDownLoad.closeFile()})// 临时处理、防止报错return new MyPara()})}}

3. 效果

PixPin_2024-10-31_20-52-33

卡片同步轮播

image-20241031224212664

该功能主要是首页在图片轮播时,通知所有的卡片同时更新

entry/src/main/ets/pages/Index.ets

1. 监听轮播图onChange事件,设置当前显示的下标

      Swiper() {ForEach(this.swiperList, (img: string) => {Image(img).width("80%")})}.loop(true).autoPlay(true).interval(3000).onChange(index => this.activeIndex = index)

2. 监听下标的改变,通知持久化存储中所有的卡片进行更新

  @StorageLink("activeIndex")@Watch("changeIndex")activeIndex: number = 0// 通知所有卡片一并更新changeIndex() {const list = FormIdStore.getList()const index = this.activeIndexlist.forEach(id => {class FdCls {activeIndex: number = index}const formInfo = formBindingData.createFormBindingData(new FdCls())formProvider.updateForm(id, formInfo)})}

3. 效果

PixPin_2024-10-31_22-18-40

总结

FormExtensionAbility进程不能常驻后台,即在卡片生命周期回调函数中无法处理长时间的任务,在生命周期调度完成后会继续存在10秒,如10秒内没有新的

生命周期回调触发则进程自动退出。针对可能需要10秒以上才能完成的业务逻辑,建议拉起主应用进行处理,处理完成后使用updateForm通知卡片进行刷

新。

1. 项目开发流程

  1. 新建项目与服务卡片:创建新的项目和服务卡片,为后续开发搭建基础框架。
  2. 设置沉浸式体验:在EntryAbility.ets中进行相关设置,优化用户视觉体验。

2. 首页轮播图数据显示

  1. 申请网络权限:在module.json5中申请,为数据获取做准备。
  2. 新建工具文件:在/utils/index.ets中创建swiperInit函数,用于初始化轮播图数据,包括设置轮播图列表和初始索引。
  3. 初始化操作:在EntryAbility.ets中进行初始化。
  4. 页面使用:在Index.ets中构建轮播图组件,通过SwiperForEach等实现轮播效果,轮播图可自动播放、循环,并能响应索引变化。

3. 卡片 id 的处理

  1. 获取与返回卡片 id:在EntryFormAbility.etsonAddForm函数中获取卡片 id,并返回给卡片组件。原因是后期卡片向应用通信时,应用需根据卡片 id 响应,同时注意formExtensionAbility进程的后台限制。
  2. 接受与显示卡片 id:在WidgetCard.ets中接受并显示卡片 id。
  3. 卡片 id 的持久化存储
    • 封装工具类:在/utils/index.ets中封装FormIdStore类,实现初始化、获取卡片 id 列表、新增和删除卡片 id 等功能。
    • 初始化工具类:在EntryAbility.etsonCreateonAddForm中初始化。
    • 卡片主动上传:在WidgetCard.ets中利用watch监听器触发上传卡片 id。
    • 应用接收与持久化:在EntryAbility.ets中接收卡片 id 并持久化,同时需开启后台运行权限。
    • 移除卡片时处理:在EntryFormAbility.etsonRemoveForm中删除卡片 id。

4. 图片相关操作

  1. 封装下载图片工具类:在CardDonwLoad.ets中封装,包括下载单张或一组图片的功能,以及手动关闭文件功能,涉及网络请求和文件操作。
  2. 卡片发起通知获取网络图片
    • 卡片准备接收数据:在WidgetCard.ets中准备接收网络图片数据的代码,包括显示图片数组、卡片 id 等相关变量和操作。
    • 应用处理与返回数据:在EntryAbility.ets中接收卡片通知,下载网络图片并返回给卡片,先响应空数据,下载完成后再更新卡片数据。

5. 卡片同步轮播功能

  1. 监听轮播图 onChange 事件:在Index.ets中通过Swiper组件的onChange事件设置当前显示下标。
  2. 通知卡片更新:在Index.ets中监听下标改变,通知持久化存储中的所有卡片更新,实现首页与卡片轮播同步。

作者

作者:万少

链接:https://www.nutpi.net/

來源:坚果派 著作权归作者所有。

商业转载请联系作者获得授权,非商业转载请注明出处。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

基于 PyTorch 从零手搓一个GPT Transformer 对话大模型

一、从零手实现 GPT Transformer 模型架构 近年来&#xff0c;大模型的发展势头迅猛&#xff0c;成为了人工智能领域的研究热点。大模型以其强大的语言理解和生成能力&#xff0c;在自然语言处理、机器翻译、文本生成等多个领域取得了显著的成果。但这些都离不开其背后的核心架…

三、整数规划

整数规划 建立逻辑变量来整合多个方案。如0-1变量&#xff08;要说明0和1分别表示什么&#xff09;见P79求解纯整数规划的分支定界法&#xff1a; 求解整数规划的松弛问题的最优解若松弛问题的最优解满足整数要求&#xff0c;则得到整数规划的最优解&#xff0c;否则转下一步任…

Docker了解

Docker是一种容器化技术&#xff0c;它可以将应用程序和其依赖项打包到一个独立的、可移植的容器中&#xff0c;以便在不同的环境中运行。Docker基于Linux操作系统的容器化技术&#xff0c;可以提供更轻量、更快速、更灵活、更一致的应用部署和管理方式。 Docker的基本概念包括…

stm32以太网接口:MII和RMII

前言 使用stm32和lwip进行网络通信开发时&#xff0c;实现结构如下&#xff1a; 而MII和RMII就是stm32与PHY芯片之间的通信接口&#xff0c;类似于I2C、UART等。 stm32以太网模块有专用的DMA控制器&#xff0c;通过AHB接口将以太网内核和存储器相连。 数据发送时&#xff0c;…

【GESP】C++一级真题练习(202312)luogu-B3921,小杨的考试

GESP一级真题练习。为2023年12月一级认证真题。逻辑计算问题。 题目题解详见&#xff1a;【GESP】C一级真题练习(202312)luogu-B3921&#xff0c;小杨的考试 | OneCoder 【GESP】C一级真题练习(202312)luogu-B3921&#xff0c;小杨的考试 | OneCoderGESP一级真题练习。为2023…

【java】通过<类与对象> 引入-> 链表

目录 链表 碎片化&#xff1a; 内存碎片产生的原因 如何避免内存碎片&#xff1f; 链表类型 单链表 双链表 单循环链表 双循环链表 java是如何创建链表的&#xff1f; 类与对象 类是什么&#xff1f; 什么是对象&#xff1f; 构建链表 头指针 简画内存图&#…

微软开源5级Agent框架,复杂任务就这么被解决了~

微软又来卷Agent&#xff0c;开源了解决复杂任务的通用Multi-Agent框架Magentic-One&#xff0c;它旨在解决开放性的网络和基于文件的任务&#xff0c;跨越各种领域&#xff0c;如操作网络浏览器、导航本地文件、编写和执行Python代码、做市场调研、写论文等等。 Magentic-One…

矩阵中的路径(dfs)-acwing

题目 23. 矩阵中的路径 - AcWing题库 代码 class Solution { public://以每一个坐标作为dfs起点bool hasPath(vector<vector<char>>& matrix, string str) {for (int i 0; i < matrix.size(); i )for (int j 0; j < matrix[i].size(); j )if (dfs(…

欢迎 Stable Diffusion 3.5 Large 加入 Diffusers

作为Stable Diffusion 3的改进版本&#xff0c;Stable Diffusion 3.5 如今已在 Hugging Face Hub 中可用&#xff0c;并可以直接使用 &#x1f9e8; Diffusers 中的代码运行。 https://hf.co/blog/sd3 本次发布包含两套模型参数: https://hf.co/collections/stabilityai/stable…

Docker入门系列——DockerFile的使用

前面了解了Docker的基本概念&#xff0c;今天来认识一下DockerFile。 Dockerfile 是一个文本文件&#xff0c;包含一系列指令来组装 Docker 镜像。每个指令执行一个特定动作&#xff0c;例如安装包、复制文件或定义启动命令。正确使用 Dockerfile 指令对于构建高效容器至关重要…

2-146 基于matlab的双摆杆系统建模分析

基于matlab的双摆杆系统建模分析。连接方式为铰接&#xff0c;两杆均视为均质杆&#xff0c;动态输出摆杆末端轨迹。程序已调通&#xff0c;可直接运行。 下载源程序请点链接&#xff1a;2-146 基于matlab的双摆杆系统建模分析

基于java+SpringBoot+Vue的美发门店管理系统设计与实现

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; Springboot mybatis Maven mysql5.7或8.0等等组成&#x…

基于vue框架的的楼盘销售管理系统6n60a(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 用户,房源类型,员工,房源信息,购房预订,购房合同 开题报告内容 基于Vue框架的楼盘销售管理系统开题报告 一、研究背景 随着房地产市场的蓬勃发展&#xff0c;楼盘销售行业的竞争日益激烈。传统的销售管理方式依赖于人工记录和纸质文档&#xff0c;效率低下…

值得一看的小模型技术全面总结及RAG文档处理及切分小模型工具

、 本文还是来看看RAG&#xff0c;不过是从另一个角度&#xff0c;从小模型(其实这个小不太好说&#xff0c;7B或者以下&#xff1f;)角度&#xff1b; 因此&#xff0c;讲两件事&#xff0c;一个是回顾下小模型&#xff0c;推荐一个写的很好的小模型进展技术总结综述&#xf…

大模型好书案例——《BERT基础教程:Transformer大模型实战》(附PDF)

《BERT基础教程&#xff1a;Transformer大模型实战》是一本关于自然语言处理&#xff08;NLP&#xff09;的书籍&#xff0c;专注于谷歌公司开发的BERT模型。这本书由印度作者苏达哈尔桑拉维昌迪兰&#xff08;Sudharsan Ravichandiran&#xff09;撰写&#xff0c;周参翻译。 …

关于Markdown的一点疑问,为什么很多人说markdown比word好用?

markdown和word压根不是一类工具&#xff0c;不存在谁比谁好&#xff0c;只是应用场景不一样。 你写博客、写readme肯定得markdown&#xff0c;但写合同、写简历肯定word更合适。 markdown和word类似邮箱和微信的关系&#xff0c;这两者都可以通信&#xff0c;但微信因为功能…

ASR 点屏

ASR翱捷科技 ASR kernel 5.10 android14 ASR EVB平台 以gc7202 jd9365这两块屏为例 新旧DTBO点屏配置是有区别的,主要差异是体现在 asr\kernel\u-boot\board\asr\dove\dovc.c这个文件上 旧DTBO: 新DTBO: 目前我们的代码已经合入新的DTBO 以前在没有合入asr新的DTBO时点亮…

Ubuntu24.04网络异常与应对方案记录

PS: 参加过408改卷的ZJU ghsongzju.edu.cn 开启嘲讽: 你们知道408有多简单吗&#xff0c;操作系统真实水平自己知道就行&#xff5e;&#xff5e; Requested credits of master in UWSC30&#xff0c;in ZJU24&#xff0c;domestic master is too simple dmesg dmesg 是一个用…

【Zynq FPGA】基于 Zynq FPGA 的雷龙 SD NAND 测试

对于芯片正常读写的测试结果&#xff0c;还是很让人满意的&#xff0c;芯片的价格也很合理。并且LGA-8封装更适合无卡槽的嵌入式开发板设计&#xff0c;在一定的应用领域有着简化硬件设计、减小硬件面积的功能。贴上测试工程的链接&#xff0c;还迎复现实验: https://gitee.com…

【PyTorch][chapter31][transformer-5] MQA,CQA, GQA

前言&#xff1a; Trans 翻译 《Variants of Multi-head attention: Multi-query (MQA) and Grouped-query attention (GQA) 为例兼顾性能,和模型的效率Google 又陆续提出了三种注意力架构. 当一个模型训练过度时&#xff0c;它会过度拟合或记忆训练数据&#xff0c;从而降低…