HarmonyOS 鸿蒙NEXT清除应用数据使用什么方法

HarmonyOS 鸿蒙NEXT清除应用数据使用什么方法

使用ApplicationContext.clearUpApplicationData清除应用数据,会使应用卡死1,2秒,如何使用户无卡顿感的清除应用数据,并退出APP呢?

3 回复

您好,具体解决方案如下:

通过loading框缓解卡顿,根据业务场景,参考以下方案:

  1. 参考LoadingProgress()。示例

  2. 通过图片旋转模拟loading效果。代码示例如下:

@Entry
@Component
struct Index {
  @State loading: boolean = false;

  build() {
    Column({ space: 20 }) {
      LoadingView({ loading: this.loading })
      Row({ space: 20 }) {
        Button('开始').onClick(() => {
          this.loading = true;
        })

        Button('结束').onClick(() => {
          this.loading = false;
        })
      }
    }
    .width('100%')
    .height('100%')
  }
}

代码运行展示:

  1. 自定义LoadingView,供全局调用。代码示例如下:

  2. 自定义LoadingView.ets。

export class LoadingTime {
  static baseTime: number = 400 //消息显示基本时间
  static wordTime: number = 90 //每个字增加显示的时间

  static minTime: number = 1600 //最短显示时间
  static maxTime: number = 4200 //最长显示时间
}

export enum LoadingType {
  Loading = 0,
  Info,
  Success,
  Error,
  Length
}

interface LoadingParam {
  msg: string,
  cancelCallBack?: () => void,
  alignment?: DialogAlignment,
  offset?: Offset,
  showInSubWindow?: boolean,
  isModal?: boolean,
  tmpHUDNum?: number, //缓存HUD的数量,用于多层返回HUD不显示情况
}

@CustomDialog
struct _LoadingView {
  controller: CustomDialogController
  close: () => void = () => {}
  type: LoadingType = LoadingType.Loading
  image: ResourceStr | undefined = undefined
  @State angle: number = 0
  @State msg: string = ""

  aboutToAppear() {
    if (this.type == LoadingType.Loading) {
      setTimeout(() => {
        this.angle = 360
      }, 100)
    }
  }

  build() {
    Column() {
      if (this.type == LoadingType.Loading) {
        Row()
          .width(px2vp(200))
          .height(px2vp(200))
          .sweepGradient({
            center: [px2vp(100), px2vp(100)],
            rotation: 280,
            start: 0,
            end: 360,
            colors:
            [['rgba(255, 255, 255, 0.0)', 0.0], ['rgba(255, 255, 255, 0.0)', 0.18], ['rgba(255, 255, 255, 1.0)', 1.0]]
          })
          .clip(new Path({
            width: 100, height: 100, commands:
            `M100 10 A90 90 0 1 0 190 100 A2 8 0 1 0 182 100 A82 82 0 1 1 100 18 A4 4 0 0 0 100 10 Z`
          }))
          .rotate({
            z: 1,
            angle: this.angle
          })
          .animation({
            duration: 1000,
            curve: Curve.Linear,
            iterations: -1,
            expectedFrameRateRange: {
              min: 20,
              max: 60,
              expected: 60,
            }
          })
          .scale({ x: 0.9, y: 0.9 })
      } else if (this.image) {
        Image(this.image)
          .fitOriginalSize(true)
          .objectFit(ImageFit.None)
      }
      if (this.msg) {
        Text(this.msg)
          .fontColor(Color.White)
          .textAlign(TextAlign.Center)
          .padding({ top: this.type == LoadingType.Loading || this.image ? 10 : 0 })
      }
    }
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
    .padding(12)
    .margin(30)
    .backgroundColor(Color.Black)
    .borderRadius(10)
    .shadow({ radius: 10, color: Color.Gray, offsetX: 3, offsetY: 0 })
  }
}

let _dialogController: CustomDialogController | null
let _cancelCallBack: (() => void) | undefined

let tmpHUDArray: LoadingView[] = new Array()

@Component
export struct LoadingView {
  showLoading(
    msg: string | LoadingParam = "",
    cancelCallBack?: () => void,
    alignment?: DialogAlignment,
    offset?: Offset,
    showInSubWindow?: boolean,
    isModal?: boolean,
    tmpHUDNum: number = 1, //缓存HUD的数量,用于多层返回HUD不显示情况
  ): void {
    if (typeof msg == 'string') {
      this.showType(LoadingType.Loading, undefined, msg, cancelCallBack, alignment, offset, showInSubWindow, isModal)
    } else {
      this.showType(LoadingType.Loading, undefined, msg.msg, msg.cancelCallBack, msg.alignment, msg.offset, msg.showInSubWindow, msg.isModal)
      tmpHUDNum = msg.tmpHUDNum ?? 1
    }

    //用于解决网络返回或者其它情况下不显示的问题
    if (tmpHUDArray.length < tmpHUDNum) {
      for (let index = 0; index < tmpHUDNum; index++) {
        tmpHUDArray.push(new LoadingView());
      }
    }
  }

  showInfo(
    msg: string | LoadingParam = "",
    cancelCallBack?: () => void,
    alignment?: DialogAlignment,
    offset?: Offset,
    showInSubWindow?: boolean,
    isModal?: boolean,
  ): void {
    if (typeof msg == 'string') {
      this.showType(LoadingType.Info, undefined, msg, cancelCallBack, alignment, offset, showInSubWindow, isModal)
    } else {
      this.showType(LoadingType.Info, undefined, msg.msg, msg.cancelCallBack, msg.alignment, msg.offset, msg.showInSubWindow, msg.isModal)
    }
  }

  showSuccess(
    msg: string | LoadingParam = "",
    cancelCallBack?: () => void,
    alignment?: DialogAlignment,
    offset?: Offset,
    showInSubWindow?: boolean,
    isModal?: boolean,
  ): void {
    if (typeof msg == 'string') {
      this.showType(LoadingType.Success, $r("app.media.wtr_success"), msg, cancelCallBack, alignment, offset, showInSubWindow, isModal)
    } else {
      this.showType(LoadingType.Success, $r("app.media.wtr_success"), msg.msg, msg.cancelCallBack, msg.alignment, msg.offset, msg.showInSubWindow, msg.isModal)
    }
  }

  showError(
    msg: string | LoadingParam = "",
    cancelCallBack?: () => void,
    alignment?: DialogAlignment,
    offset?: Offset,
    showInSubWindow?: boolean,
    isModal?: boolean,
  ): void {
    if (typeof msg == 'string') {
      this.showType(LoadingType.Error, $r("app.media.wtr_error"), msg, cancelCallBack, alignment, offset, showInSubWindow, isModal)
    } else {
      this.showType(LoadingType.Error, $r("app.media.wtr_error"), msg.msg, msg.cancelCallBack, msg.alignment, msg.offset, msg.showInSubWindow, msg.isModal)
    }
  }

  showType(
    type: LoadingType,
    image: Resource | undefined,
    msg: string,
    cancelCallBack?: () => void,
    alignment: DialogAlignment = DialogAlignment.Center,
    offset: Offset = { dx: 0, dy: 0 },
    showInSubWindow: boolean = false,
    isModal: boolean = false,
    useTmpHUD: boolean = true //是否使用缓存的HUD
  ): void {
    let self: LoadingView | undefined = this
    if (useTmpHUD && tmpHUDArray.length > 0) {
      self = tmpHUDArray.shift()
    }
    self?.showTypeReal(type, image, msg, cancelCallBack, alignment, offset, showInSubWindow, isModal)
  }

  private showTypeReal(
    type: LoadingType,
    image: Resource | undefined,
    msg: string,
    cancelCallBack?: () => void,
    alignment: DialogAlignment = DialogAlignment.Center,
    offset: Offset = { dx: 0, dy: 0 },
    showInSubWindow: boolean = false,
    isModal: boolean = false,
  ): void {
    this.hide()

    _cancelCallBack = cancelCallBack

    let animate: AnimateParam = {
      duration: 90,
      delay: 0,
      curve: Curve.EaseInOut
    }

    _dialogController = new CustomDialogController({
      builder: _LoadingView({ type: type, image: image, msg: msg }),
      autoCancel: false,
      cancel: () => {
        _dialogController = null
        if (_cancelCallBack) {
          _cancelCallBack()
        }
      },
      customStyle: true,
      alignment: alignment,
      offset: offset,
      maskColor: 0x33000000,
      openAnimation: animate,
      closeAnimation: animate,
      showInSubWindow: showInSubWindow,
      isModal: isModal, //api 11 是否有蒙层
    })
    _dialogController.open()
    if (type != LoadingType.Loading) {
      let time: number = LoadingTime.baseTime;
      if (msg) {
        time += msg.length * LoadingTime.wordTime
      }
      time = Math.max(time, LoadingTime.minTime)
      time = Math.min(time, LoadingTime.maxTime)
      setTimeout(() => {
        this.hide()
      }, time)
    }
  }

  hide() {
    if (_dialogController) {
      _dialogController.close()
      _dialogController = null
      if (_cancelCallBack) {
        _cancelCallBack()
      }
    }
  }

  build() {
  }
}

引入使用。

import { LoadingView } from './LoadingView'

@Entry
@Component
struct Index {
  loadingView:LoadingView = new LoadingView()

  build() {
    NavDestination() {
      Column({ space: 30 }) {
        Button('Toast提示有文案')
          .onClick(() => {
            this.loadingView.showLoading({msg:'数据加载中'})
            setTimeout(() => {
              this.loadingView.hide()
            }, 1000)
          })
        Button('loading有蒙层')
          .onClick(() => {
            this.loadingView.showLoading({msg:'数据加载中',isModal:true})
            setTimeout(() => {
              this.loadingView.hide()
            }, 1000)
          })
        Button('信息提示')
          .onClick(() => {
            this.loadingView.showInfo("这里是Toast提示信息")
          })
        Button('成功')
          .onClick(() => {
            this.loadingView.showSuccess("数据加载成功")
          })
        Button('失败')
          .onClick(() => {
            this.loadingView.showError("数据加载失败")
          })
        Button('Toast')
          .onClick(() => {
            this.loadingView.showLoading()
            setTimeout(() => {
              this.loadingView.hide()
            }, 1000)
          })
      }
    }
    .height('100%')
    .width('100%')
  }
}

更多关于HarmonyOS 鸿蒙NEXT清除应用数据使用什么方法的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS NEXT中清除应用数据,可通过以下方式操作:

  1. 系统设置路径:

    • 设置 > 应用管理 > 选择目标应用 > 存储 > 清除数据/清除缓存
  2. 命令行方式(需ADB调试权限):

    adb shell pm clear <package_name>
    
  3. 应用内管理(部分应用支持):

    • 应用设置页中的"清除数据"选项

该方法会移除应用所有本地数据(账号/配置等),但不会卸载应用。系统应用数据清除可能需要特殊权限。

在HarmonyOS Next中,要优化清除应用数据的体验,可以考虑以下方法:

async function clearAppData() {
    // 先退出应用
    await App.exit();
    
    // 在后台线程执行清除操作
    TaskDispatcher.globalTaskDispatcher().dispatch(() => {
        const context = AbilityContext.getApplicationContext();
        context.clearUpApplicationData();
    });
}
function clearDataGradually() {
    // 1. 先清除缓存
    CacheManager.clearAll();
    
    // 2. 异步清除数据库
    TaskDispatcher.globalTaskDispatcher().dispatch(() => {
        DatabaseHelper.clearAllDatabases();
    });
    
    // 3. 最后清除首选项
    Preferences.deleteAllPreferences();
    
    // 退出应用
    App.exit();
}

使用进度提示: 在清除数据前显示进度条或提示信息,提升用户体验感知。

注意:直接调用clearUpApplicationData()是同步操作且会清除所有数据,建议根据实际需求选择部分清除或异步处理方案。

回到顶部