HarmonyOS 鸿蒙Next 在Promise中读取远程数据并写入文件,通过callback回调进度刷新UI的问题:@State数据变化不立即刷新UI

发布于 1周前 作者 eggper 来自 鸿蒙OS

HarmonyOS 鸿蒙Next 在Promise中读取远程数据并写入文件,通过callback回调进度刷新UI的问题:@State数据变化不立即刷新UI 在Promise中,读取远程数据并写入到文件,通过callback回调进度从而刷新UI。但是@State对应的数据有变化,UI并不会立即刷新

export class DownloadViewModel {

  downloadCallback:(progress:number)=>void =()=>{}

  download(){
    let promise: Promise<number> = new Promise((resolve: Function, reject: Function) => {
      let sessionId = 0

      if (sessionId < 0) {
        //回调进度 失败
        reject()
        return
      }
      this.isDownloadingFile = true
      this.downloadFileTimeOutId = setTimeout(() => {
        if (!this.isDownloadingFile) {
          return
        }
        if (this.rdtId >= 0) {
          cameraNapi.RDT_Destroy(this.rdtId)
          this.rdtId = -1
        }
        this.rdtId = cameraNapi.RDT_Create(sessionId, this.RDT_TIME_OUT, this.uploadOrDownloadChannelID)

        try {
          if (this.rdtId >= 0 && this.isDownloadingFile) {

            let sendRDTCommand = new Uint8Array(128)
            sendRDTCommand[0] = RDCTRLDEFs.RDT_COMMAND_FILE_NAME.valueOf()
            let name = Uint8ArrayUtils.strToUint8Array(path)
            sendRDTCommand.set(name, 1)

            let result = cameraNapi.RDT_Write(this.rdtId, sendRDTCommand)
            this.log("downloadFile RDT_Write result=" + result)
            if (result >= 0 && this.rdtId >= 0) {
              let recvBuffer = new Uint8Array(1024)

              result = cameraNapi.RDT_Read(this.rdtId, recvBuffer, this.RDT_TIME_OUT)
              this.log("downloadFile RDT_Read result=" + result)
              if (result > 0) {
                this.log("downloadFile RDT_Read type=" + recvBuffer[0])

                if (recvBuffer[0] == RDCTRLDEFs.RDT_COMMAND_FILE_SIZE.valueOf()) {

                  let sizeArray = Packet.uint8ArrayToUint8Array(recvBuffer, 1, 8)
                  let fileTotalSize = Number(Uint8ArrayUtils.uint8ArrayToStr(sizeArray))
                  this.log("downloadFile fileSize=" + fileTotalSize)

                  let startContent = this.getRDTSendFileContent(RDCTRLDEFs.RDT_COMMAND_FILE_START.valueOf(), "Start")

                  result = cameraNapi.RDT_Write(this.rdtId, startContent)
                  this.log("downloadFile start send result=" + result)

                  if (result >= 0) {
                    let status: RDT_Status = {
                      Timeout: 0,
                      TimeoutThreshold: 0,
                      BufSizeInSendQueue: 0,
                      BufSizeInRecvQueue: 0
                    }
                    let check = cameraNapi.RDT_Status_Check(this.rdtId, status)
                    if (check >= 0) {
                      let readTotal = 0
                      if (this.saveFile) {
                        fs.closeSync(this.saveFile)
                        this.saveFile = undefined
                      }
                      this.saveFile = fs.openSync(savePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE)
                      let writeOptions: WriteOptions = {
                        length: 1024
                      }
                      this.downloadCallback(0)
                      let lastProgress = 0
                      do {

                        let recvBuffer = new Uint8Array(1024)
                        // recvBuffer.fill(0)
                        result = cameraNapi.RDT_Read(this.rdtId, recvBuffer, this.RDT_TIME_OUT)
                        this.log("download read length=" + result)
                        if (result > 0) {
                          writeOptions.length = result
                          //内容写入文件
                          fs.write(this.saveFile.fd, recvBuffer.buffer, writeOptions)
                          readTotal += result
                          writeOptions.offset = readTotal

                          let progress = Math.floor(readTotal / fileTotalSize * 100)

                          if(lastProgress != progress){
                            this.downloadCallback(progress)
                          }

                        } else {
                          break
                        }

                      } while (this.isDownloadingFile && readTotal < fileTotalSize && this.rdtId >= 0)
                      let progress = Math.floor(readTotal / fileTotalSize * 100)
                      this.downloadCallback(progress)
                      // this.uploadOrDownloadProgress(path, 0, progress, 1)

                      resolve(1)
                    }
                    if (this.saveFile) {
                      fs.closeSync(this.saveFile)
                      this.saveFile = undefined
                    }
                  } else {
                    if (this.saveFile) {
                      fs.closeSync(this.saveFile)
                      this.saveFile = undefined
                    }
                    reject()
                  }

                  let endContent = this.getRDTSendFileContent(RDCTRLDEFs.RDT_COMMAND_FILE_STOP, "Stop")
                  cameraNapi.RDT_Write(this.rdtId, endContent)
                } else {
                  if (this.saveFile) {
                    fs.closeSync(this.saveFile)
                    this.saveFile = undefined
                  }
                  reject()
                }

              } else {
                if (this.saveFile) {
                  fs.closeSync(this.saveFile)
                  this.saveFile = undefined
                }
                reject()
              }

            } else {
              if (this.saveFile) {
                fs.closeSync(this.saveFile)
                this.saveFile = undefined
              }
              reject()
            }


          } else {
            if (this.saveFile) {
              fs.closeSync(this.saveFile)
              this.saveFile = undefined
            }
            reject()
          }
        } catch (e) {
          if (this.saveFile) {
            fs.closeSync(this.saveFile)
            this.saveFile = undefined
          }
          reject()
        }

        if (this.rdtId >= 0) {
          cameraNapi.RDT_Destroy(this.rdtId)
          this.rdtId = -1
        }
        this.stopDownload()
      }, 500)
    })

    return promise
  }
}

@Component
export struct DownloadPage{

  [@State](/user/State) progress:number = 0

  private downloadViewModel:DownloadViewModel = new DownloadViewModel()

  private download(){
    this.downloadViewModel.downloadCallback = (progress:number)=>{
      this.progress = progress
    }
  }

  build() {
    Column(){
      Progress({
        value:this.progress
      })
      Button("下载")
        .onClick(()=>{
          this.download()
        })
    }
  }
}

更多关于HarmonyOS 鸿蒙Next 在Promise中读取远程数据并写入文件,通过callback回调进度刷新UI的问题:@State数据变化不立即刷新UI的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于HarmonyOS 鸿蒙Next 在Promise中读取远程数据并写入文件,通过callback回调进度刷新UI的问题:@State数据变化不立即刷新UI的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS鸿蒙Next中,如果在Promise中读取远程数据并写入文件,同时希望通过callback回调来刷新UI,但遇到@State数据变化不立即刷新UI的问题,通常这是因为UI刷新依赖于系统的事件循环机制。在异步操作中,UI刷新可能会被延迟,直到当前事件循环结束。

要解决这个问题,你可以考虑以下几种方法:

  1. 使用@ObservedObject@EnvironmentObject:这些属性包装器可以确保对象在数据变化时自动通知UI进行刷新。

  2. 调度到主线程:确保UI更新操作在主线程执行。HarmonyOS可能提供类似SwiftUI的DispatchQueue.main.async的方法,用于将更新操作调度到主线程。

  3. 利用ObjectWillChange:手动触发对象的变化通知。在你的数据模型中,可以调用objectWillChange.send()来通知视图刷新。

  4. 检查数据绑定:确保你的数据绑定正确无误,@State变量确实与UI组件相关联。

如果上述方法仍然无法解决问题,可能是由于特定的实现细节或系统限制。此时,建议深入检查你的代码逻辑,或者查阅HarmonyOS的官方文档以获取更多关于异步UI更新的指导。如果问题依旧没法解决请联系官网客服,官网地址是 https://www.itying.com/category-93-b0.html

回到顶部