鸿蒙应用开发实战【95】— 实战应用状态批量管理操作

鸿蒙应用开发实战【95】— 实战应用状态批量管理操作

本文是「号码助手全栈开发系列」第 95 篇,持续更新中…
开源社区:https://openharmonycrossplatform.csdn.net


前言

批量操作是提升用户效率的关键功能。号码助手的首页支持多选模式,用户可一次性对多个应用进行状态变更(换绑 / 注销)或删除。本篇讲解选择模式状态管理、批量操作栏 UI 和 DAO 层的批量操作实现。

本篇涵盖:选择模式(selectMode)状态机、Swipe 手势切换、批量操作栏(BulkActionBar)、选中 IDs 管理、批量状态更新batchUpdateStatus、批量删除deleteMany


一、选择模式状态机

文件pages/HomePage.ets

@StateselectMode:boolean=false// 是否处于选择模式@StateselectedIds:number[]=[]// 选中的应用绑定 id 列表

状态转换

普通模式 ──长按应用列表──→ 选择模式 选择模式 ──点击"取消"──→ 普通模式 选择模式 ──执行批量操作──→ 普通模式 选择模式 ──选中 0 项──→ 普通模式(自动退出)

二、进入选择模式

2.1 长按触发

// AppListItem 组件中@BuilderAppListItem(item:AppRow){Column().gesture(LongPressGesture({duration:500}).onAction(()=>{this.enterSelectMode()this.toggleSelection(item.binding.id!)}))}

2.2 切换选中状态

privatetoggleSelection(id:number):void{constidx=this.selectedIds.indexOf(id)if(idx>=0){this.selectedIds.splice(idx,1)}else{this.selectedIds.push(id)}// 选中状态变更数组引用(触发 @State 更新)this.selectedIds=[...this.selectedIds]// 如果取消选中最后一个,自动退出选择模式if(this.selectedIds.length===0){this.selectMode=false}}

三、批量操作栏(BulkActionBar)

进入选择模式后,底部出现批量操作栏:

┌─────────────────────────────────────────┐ │ 已选中 3 项 换绑 注销 删除 │ └─────────────────────────────────────────┘
// 选择模式时的底部操作栏if(this.selectMode){Row(){Text(`已选中${this.selectedIds.length}`).fontSize(AppFonts.BODY).fontColor(AppColors.TEXT_2).layoutWeight(1)Text('换绑').onClick(()=>this.batchRebind())Text('注销').onClick(()=>this.batchCancel())Text('删除').fontColor(AppColors.DANGER).onClick(()=>this.batchDelete())}.width('100%').height(56).padding({left:16,right:16}).backgroundColor(AppColors.CARD_B).border({width:{top:1},color:AppColors.LINE})}

四、DAO 层批量操作

4.1 批量更新状态

文件features/data/AppBindingDao.ets

/** * 批量更新应用绑定状态 * @param ids 要更新的记录 id 列表 * @param newStatus 目标状态 */staticasyncbatchUpdateStatus(ids:number[],newStatus:BindingStatus):Promise<number>{try{conststore=AppBindingDao.getStore()constpredicates=newrelationalStore.RdbPredicates(TABLE)predicates.in('id',ids.map(String))// IN 查询constvalues:relationalStore.ValuesBucket={status:newStatus,updated_at:Date.now()}constaffectedRows=awaitstore.update(values,predicates)hilog.info(0x0000,TAG,'batchUpdateStatus: %{public}d 行受影响',affectedRows)returnaffectedRows}catch(e){hilog.error(0x0000,TAG,'batchUpdateStatus 失败: %{public}s',JSON.stringify(e))thrownewError('batchUpdateStatus 失败: '+JSON.stringify(e))}}

4.2 批量删除

/** * 批量删除应用绑定 * @param ids 要删除的记录 id 列表 */staticasyncdeleteMany(ids:number[]):Promise<number>{try{conststore=AppBindingDao.getStore()constpredicates=newrelationalStore.RdbPredicates(TABLE)predicates.in('id',ids.map(String))constaffectedRows=awaitstore.delete(predicates)hilog.info(0x0000,TAG,'deleteMany: %{public}d 行删除',affectedRows)returnaffectedRows}catch(e){hilog.error(0x0000,TAG,'deleteMany 失败: %{public}s',JSON.stringify(e))thrownewError('deleteMany 失败: '+JSON.stringify(e))}}

五、批量换绑完整流程

privateasyncbatchRebind():Promise<void>{if(this.selectedIds.length===0)returntry{// 1. 将所有选中项改为"待换绑"awaitAppBindingDao.batchUpdateStatus(this.selectedIds,'待换绑')// 2. 刷新首页数据awaitthis.loadData()// 3. 退出选择模式this.selectMode=falsethis.selectedIds=[]promptAction.showToast({message:`已将${ids.length}项标记为待换绑`})}catch(e){hilog.error(0x0000,TAG,'batchRebind failed: %{public}s',JSON.stringify(e))promptAction.showToast({message:'批量操作失败,请重试'})}}

六、关键 predicates API

批量操作依赖RdbPredicates.in()实现:

// predicates 链式调用constpredicates=newrelationalStore.RdbPredicates('app_bindings')predicates.in('id',['1','2','3'])// WHERE id IN (1,2,3)// 生成的 SQL// UPDATE app_bindings SET status = ?, updated_at = ? WHERE id IN (1,2,3)// DELETE FROM app_bindings WHERE id IN (1,2,3)

七、UI 层级结构

HomePage ├── 标题栏(selectMode 为 true 时显示"取消"按钮) ├── 统计卡片(选择模式下半透明) ├── 应用列表(带选中态勾选标记) │ └── ForEach → AppListItem │ ├── 普通模式:显示状态标签 │ └── 选择模式:显示勾选框 ├── 三维筛选面板(选择模式下隐藏) └── 批量操作栏(仅选择模式下显示)

选中态 UI 实现:

// AppListItem 选中样式Column().opacity(rowSelected?0.7:1)// 选中项半透明.border({width:rowSelected?1:0,color:AppColors.PRIMARY,radius:14})

八、Swipe 手势切换选择模式

除了长按,还可以通过横向滑动切换选择模式:

// SwipeGesture 手势Column().gesture(SwipeGesture({direction:SwipeDirection.Left}).onAction((event:GestureEvent)=>{if(event.offsetX<-50){// 左滑超过 50pxthis.enterSelectMode()}}))

小结

功能实现关键代码适用场景
选择模式@State selectMode + toggleSelection长按触发批量管理
选中管理selectedIds 数组 + 引用替换触发刷新[...this.selectedIds]选中计数的 State 更新
批量更新状态AppBindingDao.batchUpdateStatus()predicates.in()标记换绑/注销
批量删除AppBindingDao.deleteMany()predicates.in()删除无用绑定
操作栏条件渲染if (this.selectMode)换绑/注销/删除三个按钮底部操作栏
手势LongPressGesture 500ms长按进入 / 左滑进入触发选择模式

如果这篇文章对你有帮助,欢迎点赞👍、收藏⭐、关注🔔,你的支持是我持续创作的动力!


相关资源:

  • 开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
  • HarmonyOS relationalStore API:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/relationalstore
  • HarmonyOS 官方文档:https://developer.huawei.com/consumer/cn/doc/
  • HarmonyOS hilog文档:https://developer.huawei.com/consumer/cn/doc/harmonyos-references/hilog
  • HarmonyOS testing:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/unit-test
  • HarmonyOS 安全与权限:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/permissions-overview