• [技术行业前沿] 开发者技术支持-基于Preferences异步持久化避免主线程阻塞的数据加载方案
    1.1 业务背景在移动应用开发中,用户数据的持久化存储是基础需求。无论是学习类应用的进度记录、电商应用的购物车数据、还是社交应用的用户设置,都需要实时保存并跨页面同步。应用通常包含多级页面导航(首页→列表页→详情页→操作页),用户在深层页面完成操作后,需要立即保存数据,并在返回上级页面时实时更新UI显示。随着数据量增加(可能达到数百条记录),数据读写操作频繁,若处理不当会严重影响用户体验。1.2 传统开发方式的痛点传统方式的问题:  - 手动在每个页面的onPageShow中重新加载数据,代码冗余  - 页面栈复杂时容易遗漏,导致数据不同步  - 无法实现真正的"实时刷新",只能在页面显示时刷新  - 多个页面同时访问数据时可能读取到旧数据需要一套完整的跨页面状态同步机制,而不是简单的生命周期刷新。  1.3 原因分析n 架构设计缺陷  未采用单例模式管理数据,导致多个页面各自创建Preferences实例,造成资源浪费和数据不一致。缺少统一的数据管理层,业务逻辑与数据持久化逻辑耦合在UI组件中。n 同步操作阻塞主线程  直接使用同步方法进行数据读写,所有操作都在主线程执行,I/O等待时间会直接反映为界面卡顿。n 缺少数据刷新机制  仅调用put()方法,未调用flush()确保数据写入磁盘,存在数据丢失风险。n 缺乏内存缓存策略  每次读取数据都从磁盘加载,频繁的磁盘I/O操作影响性能。 1.4 解决思路&方案 (1)核心设计思想v 全局状态管理使用AppStorage实现跨页面的状态共享,悬浮组件的显示状态、位置信息、业务数据等都存储在全局状态中。通过@StorageLink装饰器实现组件与全局状态的双向绑定。v 单例模式 + 异步初始化  采用单例模式确保全局唯一的数据管理器实例,避免重复初始化。使用async/await异步初始化Preferences,确保初始化完成后再进行数据操作,避免阻塞主线程。v 内存缓存 + 异步持久化双层架构  在内存中维护数据缓存(如learnedWords数组),所有读取操作直接从内存获取,响应速度快。写入操作先更新内存缓存,再异步写入磁盘,避免阻塞UI线程。v 异步方法 + flush()确保数据安全  使用await preferences.put()异步写入数据,配合await preferences.flush()强制刷新到磁盘,确保数据不丢失。在try-catch块中捕获异常,记录错误日志便于排查问题。v 跨页面状态同步机制  结合@StorageLink + @Watch + AppStorage三件套,实现数据变化时自动通知相关页面刷新UI,无需手动在每个页面的生命周期中重新加载数据。 (2)实现要点v 单例模式管理器设计  定义DataManager类(可根据业务命名,如UserDataManager、ProgressManager等),使用私有构造函数和静态getInstance()方法实现单例。内部维护dataPreferences实例和数据内存缓存。  ```typescript  export class DataManager {    private static instance: DataManager | null = null    private dataPreferences: preferences.Preferences | null = null    private dataCache: DataItem[] = []  // 内存缓存      private constructor() {}      public static getInstance(): DataManager {      if (!DataManager.instance) {        DataManager.instance = new DataManager()      }      return DataManager.instance    }  }  ``` v 异步初始化流程  在aboutToAppear生命周期中异步初始化管理器,使用await确保初始化完成。初始化包括获取Preferences实例和加载历史数据到内存缓存。  ```typescript  public async init(): Promise<void> {    if (!this.context) {      console.error('[DataManager] Context未设置')      return    }    try {      // 异步获取Preferences实例(存储名称根据业务自定义)      this.dataPreferences = await preferences.getPreferences(this.context, 'appData')      // 异步加载历史数据到内存      await this.loadData()      console.info('[DataManager] 初始化成功')    } catch (err) {      const error = err as BusinessError      console.error(`[DataManager] 初始化失败: ${error.code} - ${error.message}`)    }  }  ``` v 异步数据加载(内存缓存)  从Preferences异步读取数据,解析JSON后存入内存数组。后续所有读取操作直接从内存获取,避免频繁磁盘I/O。  ```typescript  private async loadData(): Promise<void> {    try {      if (this.dataPreferences) {        const data = await this.dataPreferences.get('dataList', '[]')        this.dataCache = JSON.parse(data as string) as DataItem[]        console.info(`[DataManager] 加载了 ${this.dataCache.length} 条数据`)      }    } catch (err) {      const error = err as BusinessError      console.error(`[DataManager] 加载失败: ${error.code} - ${error.message}`)      this.dataCache = []    }  }  ``` v 异步数据保存(关键:flush()确保写入)  先将数据序列化为JSON字符串,使用await put()异步写入,再使用await flush()强制刷新到磁盘。这是确保数据不丢失的关键步骤。  【强调】1. put()方法只是将数据写入内存缓冲区,并未真正写入磁盘  2. 系统会在合适的时机批量刷新缓冲区,但时机不确定  3. 如果应用崩溃或被杀死,缓冲区数据会丢失  4. flush()强制立即将缓冲区数据写入磁盘,确保数据安全  5. 这是官方文档中容易被忽略的关键细节    ```typescript  private async saveData(): Promise<void> {    try {      if (this.dataPreferences) {        // 步骤1:异步写入数据到内存缓冲区        await this.dataPreferences.put('dataList', JSON.stringify(this.dataCache))                // 步骤2:【关键】强制刷新到磁盘,确保数据不丢失        await this.dataPreferences.flush()                console.info(`[DataManager] 保存了 ${this.dataCache.length} 条数据`)      }    } catch (err) {      const error = err as BusinessError      console.error(`[DataManager] 保存失败: ${error.code} - ${error.message}`)    }  }  ```    【常见错误示例】  ```typescript  // ❌ 错误:忘记调用flush(),数据可能丢失  await this.dataPreferences.put('data', value)    // ✅ 正确:必须调用flush()确保写入磁盘  await this.dataPreferences.put('data', value)  await this.dataPreferences.flush()  ``` v 业务方法实现(内存操作 + 异步持久化)  业务方法先操作内存缓存(快速响应),再调用异步保存方法持久化到磁盘(不阻塞UI)。  ```typescript  public async addData(item: DataItem): Promise<boolean> {    // 检查是否已存在(内存操作,快速)    const exists = this.dataCache.some((d: DataItem) => d.id === item.id)    if (exists) {      console.info(`[DataManager] 数据已存在: ${item.id}`)      return false    }    // 添加到内存缓存    this.dataCache.push(item)    // 异步持久化(不阻塞UI)    await this.saveData()    console.info(`[DataManager] 添加数据成功: ${item.id}`)    return true  }  ``` v 页面中的使用方式  在页面的aboutToAppear中初始化管理器,使用.then()处理初始化完成后的逻辑,使用.catch()处理初始化失败的情况。  ```typescript  aboutToAppear(): void {    const context = getContext(this) as common.UIAbilityContext    dataManager.setContext(context)        dataManager.init().then(() => {      // 初始化完成后加载数据      this.items = this.getItems()      this.isLoaded = true    }).catch(() => {      // 即使初始化失败也显示数据(使用默认值)      this.items = this.getItems()      this.isLoaded = true    })  }  ``` v 跨页面状态同步实现  使用AppStorage全局存储刷新计数器,配合@StorageLink和@Watch实现自动刷新。这是解决多级页面导航数据同步的完整方案。  ```typescript  // 步骤1:定义全局刷新触发器(在数据管理器文件中)  export class PageRefreshTrigger {    static triggerRefresh(): void {      const currentCount = AppStorage.get<number>('pageRefreshCount') || 0      AppStorage.set('pageRefreshCount', currentCount + 1)      console.info('[PageRefreshTrigger] 触发刷新, count=' + (currentCount + 1))    }  }    // 步骤2:在数据变化时调用触发器(详情页中)  async saveData(): Promise<void> {    const success = await dataManager.addData(this.dataItem)    if (success) {      // 数据保存成功后,触发全局刷新      PageRefreshTrigger.triggerRefresh()      promptAction.showToast({ message: '保存成功!', duration: 1000 })    }    setTimeout(() => { router.back() }, 800)  }    // 步骤3:在需要刷新的页面中监听(列表页中)  @Entry  @Component  struct ListPage {    @State items: DataItem[] = []    @State isLoaded: boolean = false        // 监听全局刷新计数器,变化时自动调用onRefreshCountChange    @StorageLink('pageRefreshCount') @Watch('onRefreshCountChange') refreshCount: number = 0        // 刷新回调:重新获取数据    onRefreshCountChange(): void {      if (this.isLoaded) {        this.items = this.getItems()  // 重新获取最新数据        console.info('[ListPage] refreshCount变化,刷新数据')      }    }  }    // 步骤4:子组件也需要响应刷新(列表组件中)  @Component  export struct ListComponent {    @Prop items: DataItem[] = []  // 接收父组件传递的数据    @StorageLink('pageRefreshCount') refreshCount: number = 0  // 同样监听刷新        // ForEach的key必须包含动态数据,确保数据变化时重新渲染    ForEach(this.items, (item: DataItem, index: number) => {      this.ItemCard(item, index)    }, (item: DataItem, index: number) => `${item.id}_${item.status}_${index}`)  }  ```    【关键技术点】  - AppStorage:应用级全局状态存储,所有页面共享  - @StorageLink:双向绑定全局状态,状态变化时自动更新  - @Watch:监听状态变化,触发回调函数  - 计数器模式:通过+1触发变化,比直接传递数据更高效  - ForEach的key优化:包含动态数据确保重新渲染1.5 总结² 核心思想:异步操作避免阻塞主线程,内存缓存提升读取性能,flush()确保数据安全,单例模式统一管理资源。² 单例模式管理数据:确保全局唯一实例,避免重复初始化和数据不一致² 异步初始化:使用async/await确保初始化完成后再操作,避免空指针异常² 内存缓存策略:读取操作从内存获取,写入操作异步持久化,平衡性能与安全² 必须调用flush():仅调用put()不能保证数据写入磁盘,必须配合flush()使用² 完善的错误处理:使用try-catch捕获异常,记录详细日志便于排查问题² 状态同步机制:结合@StorageLink + @Watch实现跨页面自动刷新 
  • 【问题求助】 【算法挑战营二十一期】错误求助?
    Some tests failed. First verdict: task 0: multiple routing rules for (0, 4)   这个意思是同一任务的两个一摸一样的通信对的路由规则,我没有去重吗?
  • [互动交流] RPA 控件里的非必填参数如何动态赋值
    动态读取不同sheet页的数据,但是不能指定sheet
  • [其他] AI学习记(语音识别)-第二集
    AI语音识别定义与解读        语音识别是人机交互的接口,是指机器/程序接收,解释声音,或理解和执行口头命令的能力。在智能时代,越来越多的场景在设计个性化的交互页面时,采用以对话为主的交互形式。一个完整的对话交互是由“听懂-理解-回答”三个步骤完成的闭环。其中,“听懂”需要语音识别技术;“理解”需要自然语言处理技术;“回答”需要语音合成技术,三个步骤环环相扣,相辅相成。语音识别技术时对话交互的开端,时保证对话交互高效准确进行的基础。        语音识别技术子20世纪50年代开始步入萌芽阶段,发展至今,主流算法模型已经经历了四个阶段,包括模板匹配阶段,模式和特征分析阶段,概率统计建模阶段和现在主流的深度神经网络阶段。目前,语音识别主流厂商主要使用端到端算法,在理想实验环境下语音识别准确率可高达98%以上。语音识别发展历程如下:
  • 国内首款基于FPGA平台的语音识别加速解决方案登陆华为云
    本帖最后由 speedy2016 于 2018-6-28 20:21 编辑国内首款基于FPGA平台的语音识别加速解决方案登陆华为云 近期,华为云与国际领先深度学习加速方案提供者深鉴科技共同发布语音识别加速引擎DDESE——DeePhi Descartes Efficient SpeechRecognition Engine,即深鉴科技笛卡尔架构高效语音识别引擎。该方案以语音识别为应用载体,对AI类应用推理计算进行全面加速。成为目前国内公有云市场上,首款基于FPGA平台的原创深度学习语音识别加速解决方案。现已全面登录华为云市场。18350近年来,云端业务发展日新月异,市场对底层硬件架构提出更高性能的要求,而FPGA的可定制化和多功能的灵活特性,与云端灵活、复杂、多变的需求“不谋而合”,继而在全球云端业务中广泛加快布局。而华为云顺应趋势,并结合自身硬件优势全面推出FPGA加速云服务器平台,应用场景覆盖基因分析、视频/图片处理、深度学习、加解密、大数据等多个领域,致力于为企业提供极致、易用、专业的FPGA加速云服务。华为云结合深鉴科技,在FPGA加速云服务器平台上发布了DDESE。该产品是以Xilinx FPGA为计算架构平台,为用户打造的一款算法、软件和硬件协同设计的推理计算加速解决方案。基于深鉴科技独有的深度压缩能力,可以在保持精度的同时将神经网络压缩超过10倍,并部署在深鉴科技自主研发的笛卡尔架构硬件平台上,其核心加速引擎能够显著降低语音识别的延时,同时达到更低的功耗。根据单句语音识别重复测试的结果,DDESE端到端语音识别的计算速度是同等级GPU(Tesla P4 + c**n)的2倍,其中LSTM部的加速比超过2.5倍。该款产品主要应用于语音识别场景,可为用户提供端到端语音识别服务。未来,深鉴科技希望依托于华为云的平台,能够在FPGA领域继续突破前沿技术,引领国际先进的深度学习加速方案,进一步赋能语音识别应用场景。目前,DDESE正面向华为云用户提供免费试用,期待更多开发者与厂商体验深鉴算法、软件、硬件协同设计的深度学习加速解决方案。DDESE体验链接:https://app.huaweicloud.com/product/00301-110982-0--0
  • [热门活动] 【云端大事件】听“鉴”智能:深鉴科技高效语音识别引擎DDESE入驻华为云市场
    本帖最后由 DeePhi 于 2018-6-19 11:11 编辑【导语】2018年4月26日星期四,北京深鉴科技有限公司入驻华为云市场,在华为云市场发布了“深鉴笛卡尔高效语音识别引擎” —— DDESE(DeePhi Descartes Efficient SpeechRecognition Engine)。该产品针基于Xilinx FPGA,针对深度神经网络(主要针对LSTM),为用户提供软硬件协同设计的快速、灵活、高效的推理计算解决方案。 【标签】华为云市场 云端大事件 FPGA LSTM加速 产品介绍DDESE是深鉴科技自主研发的高效端到端自动语音识别引擎,它使用了算法、软件、硬件协同设计的深度学习加速解决方案(包括剪枝、定点、编译和FPGA执行推理)。我们使用了DeepSpeech2框架和LibriSpeech 1000小时数据集来做模型训练和压缩,支持用户测试对比CPU/FPGA的性能以及执行单句语音识别。 产品特色业界领先的原创深度学习语音识别加速解决方案 (ESE,FPGA2017 best paper)- 针对模型推理支持对单向、双向LSTM使用FPGA做加速- 支持卷积层、全连接层、BN层和多种激活函数(例如Sigmoid、Tanh和HardTanh)- 支持测试CPU/FPGA的性能比较以及单句语音识别17727 解决方案我们的解决方案包括算法、软件和硬件协同设计(包括剪枝、定点、编译和FPGA执行推理)。经过剪枝,可以在精度损失很小的情况下得到稀疏模型(稠密度为15%~20%),然后将模型的权重和激活值定点到16bit,这样一来整个模型能够被压缩超过10倍,可以借助稀疏存储格式编译并部署在深鉴科技自主研发的笛卡尔平台上,采用FPGA执行高效的推理。14590 应用场景/行业DDESE聚焦语音识别场景,构建了以赛灵思FPGA为平台的自动语音识别系统加速引擎,可以为用户提供端到端的语音识别服务。基于FPGA平台,结合深鉴科技算法、软件和硬件协同设计的深度学习加速解决方案,DDESE在语音识别端到端的计算速度是同等级GPU(Tesla P4)的2倍,其中LSTM部分的加速比超过2.5倍。深鉴科技在云端部署FPGA加速解决方案,面向全球用户提供加速服务,支持其降低开发与部署成本,消除硬件壁垒,同时通过软硬件协同优化,取得更高效的云端计算能力。 产品价值点深鉴科技的核心加速引擎主要针对RNN/LSTM,能够显著的降低语音识别、机器翻译等AI时序类应用的延时。深鉴科技在华为云市场发布DDESE,目的是以语音识别为应用载体,展现基于Xilinx FPGA的AI类应用推理计算加速能力,并通过云端推广,让更多客户试用并深入了解深鉴科技的全流程解决方案。关于DDESE的更多信息,请参考深鉴科技官网:http://www.deephi.com/zh-cn/ddese.html