Skip to content

我的模块

打卡

打卡逻辑

目标:实现打卡,已登录打卡后跳转打卡记录页面,未登录跳登录页

alt text

实现步骤:

  • 封装一个打卡工具函数,打卡成功后需要更新 User 打卡次数
  • 首页和我的页面调用,准备一个打卡页面

落地代码:

1)工具函数 utils/index.ets

ts
import { promptAction, router } from '@kit.ArkUI'
import { auth } from './Auth'
import { http } from './Http'


interface ClockRes {
  clockinNumbers: number
}

export const requestClockIn = async () => {
    const user = auth.getUser()
    if (user.token) {
      if (user.clockinNumbers === 0) {
        const res = await http.request<ClockRes>({ url: 'clockin', method: 'post' })
        user.clockinNumbers = res.clockinNumbers
        auth.setUser(user)
        promptAction.showToast({ message: '打卡成功' })
      }
      router.pushUrl({ url: 'pages/ClockInPage' })
    } else {
      router.pushUrl({ url: 'pages/LoginPage' })
    }
}

2)调用打卡

HomePage.ets

ts
  @StorageProp(UserStoreKey) user: User = {} as User

  // ...
        HcClockIn({ clockInCount: this.user.clockinNumbers })
          .onClick(() => {
            requestClockIn()
          })

MinePage.ets

ts
        HcClockIn({ clockInCount: this.user.clockinNumbers })
          .onClick(() => {
            requestClockIn()
          })

ClockInPage.ets

ts
@Entry
@Component
struct ClockInPage {

  build() {
    Column(){
      Text('打卡')
    }
    .height('100%')
    .width('100%')
  }
}

打卡页面

目标:基于 @ohmos/calendar 实现打卡页面

实现步骤:

落地代码:

1)基本结构

ts
import { HcNavBar } from '../commons/components'

interface DayBuilderParams {
  day: number
  text: string
}

@Entry
@Component
struct ClockInPage {

  @Builder
  dayBuilder(params: DayBuilderParams) {
    Column() {
      Row() {
        Text(params.day.toString())
          .fontSize(40)
          .fontWeight(FontWeight.Bold)
        Text('天')
          .fontSize(10)
          .fontColor($r('app.color.common_gray_01'))
          .margin({ bottom: 8, left: 10 })
      }
      .alignItems(VerticalAlign.Bottom)

      Text(params.text)
        .fontSize(10)
        .fontColor($r('app.color.common_gray_01'))
    }.margin({ right: 36 })
  }

  build() {
    Column({ space: 16 }) {
      HcNavBar({ title: '每日打卡', showRightIcon: false })
      Row() {
        this.dayBuilder({ day: 100, text: '累计打卡' })
        this.dayBuilder({ day: 10, text: '连续打卡' })
      }
      .padding({ top: 10, bottom: 25, left: 16, right: 16 })
      .width('100%')
      .justifyContent(FlexAlign.Start)

      Row() {
        Row()
          .width('100%')
          .height(350)
          .borderRadius(8)
          .border({ width: 0.5, color: '#ededed' })
          .shadow({ color: '#ededed', radius: 16 })
          .backgroundColor($r('app.color.white'))
      }
      .padding({ left: 16, right: 16 })
    }
    .width('100%')
    .height('100%')
    .backgroundImage($r('app.media.clocked_bg'))
    .backgroundImageSize({ width: '100%' })
  }
}

2)使用日历组件

bash
ohpm install @ohmos/calendar
ts
import { HmCalendar } from '@ohmos/calendar'
ts
        HmCalendar({
          selectedDays: [
            { date: '2024-08-11' },
          ]
        })
          .borderRadius(8)
          .border({ width: 0.5, color: '#ededed' })
          .shadow({ color: '#ededed', radius: 16 })
          .backgroundColor($r('app.color.white'))

切换月份

目标:实现打卡页数据展示,实现月份切换功能

实现步骤:

  • 查看接口文档,定义查询参数类型和响应数据类型
  • 组件初始化,调用获取数据方法获取数据,渲染页面
  • 使用切换月份事件,改变的时候重新获取数据,选中当前月份打卡天数

落地代码:

1)参数类型,数据类型 models/index.ets

ts
export interface ClockInItem {
  id: string,
  createdAt: string
}

export interface ClockInfo {
  flag: boolean
  clockinNumbers: number
  totalClockinNumber: number
  clockins: ClockInItem[]
}

export interface ClockInfoParams {
  year: string,
  month: string
}

2)初始化获取数据渲染页面 ClockInPage.ets

ts

  @State clockInfo: ClockInfo = {
    flag: false,
    clockinNumbers: 0,
    totalClockinNumber: 0,
    clockins: []
  }

  @State selectedDays: HmCalendarSelectedDay[] = []

  aboutToAppear(): void {
    const current = new Date()
    this.getClockInfo({ year: current.getFullYear().toString(), month: (current.getMonth() + 1).toString() })
  }

  async getClockInfo (params: ClockInfoParams) {
    const res = await http.request<ClockInfo>({ url: 'clockinInfo', params })
    this.clockInfo = res
    this.selectedDays = res.clockins.map(item=>({ date: item.createdAt } as HmCalendarSelectedDay))
  }
ts
      Row() {
        this.dayBuilder({ day: this.clockInfo.totalClockinNumber, text: '累计打卡' })
        this.dayBuilder({ day: this.clockInfo.clockinNumbers, text: '连续打卡' })
      }

      // ...

        HmCalendar({
          selectedDays: this.selectedDays
        })

3)切换月份

ts
        HmCalendar({
          selectedDays: this.selectedDays,
          onChangeMonth: month => {
            const arr = month.split('-')
            this.getClockInfo({ year: arr[0], month: arr[1] })
          }
        })

累计学时

累计学时-页面

目标:熟悉累计学时页面结构

ts
import { HcNavBar } from '../commons/components/HcNavBar'

@Entry
@Component
struct StudyTimePage {
  @StorageProp('bottomHeight') bottomHeight: number = 0

  @Builder
  ProgressBuilder(title: string, done: number, total: number, color: string = '#87E0CD') {
    GridCol() {
      Column() {
        Row() {
          Text(title)
            .fontColor($r('app.color.common_gray_01'))
            .fontSize(14)
          Text('10%')
            .fontColor($r('app.color.common_gray_01'))
            .fontSize(14)
        }
        .width('100%')
        .justifyContent(FlexAlign.SpaceBetween)
        .margin({ bottom: 5 })

        Progress({ value: done, total: total })
          .color(color)
          .width('100%')
      }
    }
  }

  @Builder
  DotBuilder(color: string, isDark: boolean) {
    Row() {
      Text()
        .width(7)
        .aspectRatio(1)
        .borderRadius(4)
        .backgroundColor(isDark ? color : $r('app.color.common_gray_01'))
        .margin({ right: 4 })
      Text(isDark ? '已学占比' : '未学占比')
        .fontSize(12)
        .fontColor(isDark ? $r('app.color.common_gray_03') : $r('app.color.common_gray_01'))
    }
  }

  build() {
    Column() {
      HcNavBar({ title: '学习数据', showRightIcon: false })
      Column() {
        Scroll() {
          Column() {
            // time
            Column() {
              Row() {
                Text('累计学习时长')
                  .margin({ right: 5 })
                  .fontColor($r('app.color.common_gray_03'))
                Image($r('sys.media.ohos_ic_public_clock'))
                  .width(16)
                  .aspectRatio(1)
                  .fillColor($r('app.color.common_green'))
              }
              .width('100%')
              .margin({ bottom: 10 })

              Row() {
                Text('100')
                  .fontSize(40)
                  .fontWeight(FontWeight.Bold)
                  .fontColor($r('app.color.common_green'))
                Text('分钟')
                  .margin({ bottom: 8, left: 8 })
                  .fontColor($r('app.color.common_green'))
              }
              .width('100%')
              .alignItems(VerticalAlign.Bottom)
            }

            // knowledge
            Text('知识点学习进度')
              .margin({ bottom: 10, top: 30 })
              .width('100%')
            GridRow({ columns: 2, gutter: 20 }) {
              this.ProgressBuilder('ArkTS', 20, 100)
              this.ProgressBuilder('ArkTS', 20, 100)
              this.ProgressBuilder('ArkTS', 20, 100)
              this.ProgressBuilder('ArkTS', 20, 100)
              this.ProgressBuilder('ArkTS', 20, 100)
              this.ProgressBuilder('ArkTS', 20, 100)
              this.ProgressBuilder('ArkTS', 20, 100)
              GridCol({ span: 2 }) {
                Row({ space: 16 }) {
                  this.DotBuilder('#87E0CD', true)
                  this.DotBuilder('#87E0CD', false)
                }
                .margin({ top: 10 })
              }
            }
            .backgroundColor($r('app.color.white'))
            .padding(16)
            .borderRadius(8)
            .shadow({ color: $r('app.color.common_gray_border'), radius: 16 })

            // project
            Text('项目学习进度')
              .margin({ bottom: 10, top: 30 })
              .width('100%')
            GridRow({ columns: 1, gutter: 20 }) {
              this.ProgressBuilder('HarmonyOS NEXT', 30, 200, '#C7B5ED')
              this.ProgressBuilder('HarmonyOS NEXT', 30, 200, '#C7B5ED')
              GridCol() {
                Row({ space: 16 }) {
                  this.DotBuilder('#C7B5ED', true)
                  this.DotBuilder('#C7B5ED', false)
                }
                .margin({ top: 10 })
              }
            }
            .backgroundColor($r('app.color.white'))
            .padding(16)
            .borderRadius(8)
            .shadow({ color: $r('app.color.common_gray_border'), radius: 16 })
          }
          .padding(16)
          .margin({ bottom: this.bottomHeight })
        }
        .scrollBar(BarState.Off)
      }
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
    .backgroundImage($r('app.media.study_time_bg'))
    .backgroundImageSize({ width: '100%' })
    .backgroundColor($r('app.color.common_gray_bg'))
  }
}

累计学时-实现

目的:实现累计学时页面数据展示

实现步骤:

  • 根据接口文档定义响应数据类型
  • 页面初始化获取数据
  • 进行渲染

落地代码:

1)数据类型 models/index.ets

ts
// 学习时间

export interface StudyTimeItem {
  id: string
  name: string
  total: number
  done: number
  undone: number
}

export interface StudyTimeCate {
  type: string,
  list: StudyTimeItem[]
}

export interface StudyTimeData {
  totalTime: number,
  studyData: StudyTimeCate[]
}

2)获取数据 StudyTimePage.ets

ts
  @State data: StudyTimeData = {
    totalTime: 0,
    studyData: []
  }
  dialog: CustomDialogController = new CustomDialogController({
    builder: HcLoadingDialog({ message: '加载中...' }),
    customStyle: true,
    alignment: DialogAlignment.Center
  })

  async aboutToAppear() {
    this.dialog.open()
    const res = await http.request<StudyTimeData>({ url: 'studyInfo' })
    this.data = res
    this.dialog.close()
  }

3)进行渲染 StudyTimePage.ets

累计学时:

ts
              Row() {
                Text(formatTime(this.data.totalTime).replace(/分钟|小时|/,''))
                  .fontSize(40)
                  .fontWeight(FontWeight.Bold)
                  .fontColor($r('app.color.common_green'))
                Text(formatTime(this.data.totalTime).replace(/\d|\./g,''))
                  .margin({ bottom: 8, left: 8 })
                  .fontColor($r('app.color.common_green'))
              }

知识点学习进度:

ts
if (this.data.studyData[0]) {
              // knowledge
              Text('知识点学习进度')
                .margin({ bottom: 10, top: 30 })
                .width('100%')
              GridRow({ columns: 2, gutter: 20 }) {
                ForEach(this.data.studyData[0].list, (item: StudyTimeItem) => {
                  this.ProgressBuilder(item.name, item.done, item.total)
                })
                GridCol({ span: 2 }) {
                  Row({ space: 16 }) {
                    this.DotBuilder('#87E0CD', true)
                    this.DotBuilder('#87E0CD', false)
                  }
                  .margin({ top: 10 })
                }
              }
              .backgroundColor($r('app.color.white'))
              .padding(16)
              .borderRadius(8)
              .shadow({ color: $r('app.color.common_gray_border'), radius: 16 })
            }

项目学习进度:

ts
if (this.data.studyData[1]) {
              // project
              Text('项目学习进度')
                .margin({ bottom: 10, top: 30 })
                .width('100%')
              GridRow({ columns: 1, gutter: 20 }) {
                ForEach(this.data.studyData[1].list, (item: StudyTimeItem) => {
                  this.ProgressBuilder(item.name, item.done, item.total, '#C7B5ED')
                })
                GridCol() {
                  Row({ space: 16 }) {
                    this.DotBuilder('#C7B5ED', true)
                    this.DotBuilder('#C7B5ED', false)
                  }
                  .margin({ top: 10 })
                }
              }
              .backgroundColor($r('app.color.white'))
              .padding(16)
              .borderRadius(8)
              .shadow({ color: $r('app.color.common_gray_border'), radius: 16 })
            }

百分比转换:

ts
          Text(title)
            .fontColor($r('app.color.common_gray_01'))
            .fontSize(14)
          Text(calcPercentage(done, total))
            .fontColor($r('app.color.common_gray_01'))
            .fontSize(14)

utils/index.ets

ts

export const calcPercentage = (done: number, total: number) => {
  return Math.round(done / total * 100) + '%'
}

常用单词

页面结构

WordPage.ets

ts
import { HcNavBar } from '../commons/components'

@Entry
@Component
struct WordPage {
  build() {
    Column() {
      HcNavBar({ title: '常用单词', showRightIcon: false })
      Row() {
        Column({ space: 4 }) {
          Text('开发常用词汇')
          Text(`共 0 个单词`)
            .fontSize(12)
            .fontColor($r('app.color.common_gray_03'))
        }
        .alignItems(HorizontalAlign.Start)

        Row() {
          Text('HarmonyOS')
            .fontSize(12)
            .fontColor($r('app.color.common_gray_01'))
          Image($r('sys.media.ohos_ic_public_arrow_down'))
            .width(16)
            .aspectRatio(1)
            .fillColor($r('app.color.common_gray_01'))
        }
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceBetween)
      .padding(16)
      .border({ width: { top: 0.5 }, color: $r('app.color.common_gray_bg') })

      Divider()
        .strokeWidth(8)
        .color($r('app.color.common_gray_bg'))

      List() {
        ForEach([1, 2, 3, 4, 5, 6, 7, 8], () => {

          ListItem() {
            Row({ space: 6 }) {
              Image($r('sys.media.ohos_ic_public_sound'))
                .width(20)
                .aspectRatio(1)
                .alignSelf(ItemAlign.Start)
                .fillColor($r('app.color.common_gray_03'))
              Column({ space: 10 }) {
                Text('title')
                  .fontWeight(FontWeight.Bold)
                Text('标题')
                  .fontSize(14)
                  .fontColor($r('app.color.common_gray_03'))
              }
              .alignItems(HorizontalAlign.Start)
              .layoutWeight(1)

              Row() {
                Text('详细代码')
                  .fontSize(12)
                  .fontColor($r('app.color.common_gray_01'))
                Image($r('sys.media.ohos_ic_public_arrow_right'))
                  .width(16)
                  .aspectRatio(1)
                  .fillColor($r('app.color.common_gray_01'))
              }
              .alignSelf(ItemAlign.End)
            }
            .padding(16)
          }
        })
      }
      .divider({
        strokeWidth: 0.5,
        color: $r('app.color.common_gray_bg')
      })
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')
  }
}

获取rawfile的文件数据

目标:获取 rawfile 中 json 文件的内容

前置准备:

落地代码:

1)根据 json 文件约定数据类型

ts
export interface WordItem {
  zh: string
  en: string
  code: string
}

type Words = Record<string, WordItem[]>

2)初始化获取数据

ts
  words: Words = {}

  aboutToAppear() {
    this.initWords()
  }

  initWords() {
    const ctx = getContext(this)
    // 获取二进制数据
    const uint8Array = ctx.resourceManager.getRawFileContentSync('word.json')
    // 实例化文本解析工具
    const textDecoder = new util.TextDecoder()
    // 解析文本
    // const jsonStr = textDecoder.decodeWithStream(uint8Array)
    const jsonStr = textDecoder.decodeToString(uint8Array)  // API12+
    // 转成对象
    this.words = JSON.parse(jsonStr) as Words
  }

根据数据渲染

根据获取的数据进行默认渲染

落地代码:

1)将来会切换分类,定义一个当前分类KEY的状态,默认是第一条

ts
  @State wordKey: string = ''

  initWords() {
    // 省略...
    // 默认显示第一个分类
    this.wordKey = Object.keys(this.words)[0]
  }

2)渲染页面

ts
Column() {
      HcNavBar({ title: '常用单词', showRightIcon: false })
      Row() {
        Column({ space: 4 }) {
          Text('开发常用词汇')
          Text(`共 ${this.words[this.wordKey].length} 个单词`)
            .fontSize(12)
            .fontColor($r('app.color.common_gray_03'))
        }
        .alignItems(HorizontalAlign.Start)

        Row() {
          Text(this.wordKey)
            .fontSize(12)
            .fontColor($r('app.color.common_gray_01'))
          Image($r('sys.media.ohos_ic_public_arrow_down'))
            .width(16)
            .aspectRatio(1)
            .fillColor($r('app.color.common_gray_01'))
        }
      }
      .width('100%')
      .justifyContent(FlexAlign.SpaceBetween)
      .padding(16)
      .border({ width: { top: 0.5 }, color: $r('app.color.common_gray_bg') })

      Divider()
        .strokeWidth(8)
        .color($r('app.color.common_gray_bg'))

      List() {
        ForEach(this.words[this.wordKey], (item: WordItem) => {

          ListItem() {
            Row({ space: 6 }) {
              Image($r('sys.media.ohos_ic_public_sound'))
                .width(20)
                .aspectRatio(1)
                .alignSelf(ItemAlign.Start)
                .fillColor($r('app.color.common_gray_03'))
              Column({ space: 10 }) {
                Text(item.en)
                  .fontWeight(FontWeight.Bold)
                Text(item.zh)
                  .fontSize(14)
                  .fontColor($r('app.color.common_gray_03'))
              }
              .alignItems(HorizontalAlign.Start)
              .layoutWeight(1)

              Row() {
                Text('详细代码')
                  .fontSize(12)
                  .fontColor(item.code ? $r('app.color.common_gray_01') : '#dddddd')
                Image($r('sys.media.ohos_ic_public_arrow_right'))
                  .width(16)
                  .aspectRatio(1)
                  .fillColor(item.code ? $r('app.color.common_gray_01'): '#dddddd')
              }
              .alignSelf(ItemAlign.End)
            }
            .padding(16)
          }
        })
      }
      .divider({
        strokeWidth: 0.5,
        color: $r('app.color.common_gray_bg')
      })
      .layoutWeight(1)
    }
    .width('100%')
    .height('100%')

选择单词分类

1)准备选择单词分类弹窗,选中当前分类

ts
@State showTypeSheet: boolean = false

@Builder
  TypeSheetBuilder() {
    Column() {
      Flex({ direction: FlexDirection.Row, wrap: FlexWrap.Wrap }) {
        ForEach(Object.keys(this.words), (key: string) => {
          Button() {
            Text(key)
              .fontSize(14)
              .fontColor(key === this.wordKey ? $r('app.color.common_green') : $r('app.color.common_gray_01'))
          }
          .backgroundColor($r('app.color.common_gray_bg'))
          .padding({ top: 6, right: 12, bottom: 6, left: 12 })
          .margin({ right: 12, bottom: 12 })
        })
      }
    }
    .padding({ left: 16, right: 16, top: 8, bottom: 34 })
  }
ts
Row() {
          Text(this.wordKey)
            .fontSize(12)
            .fontColor($r('app.color.common_gray_01'))
          Image($r('sys.media.ohos_ic_public_arrow_down'))
            .width(16)
            .aspectRatio(1)
            .fillColor($r('app.color.common_gray_01'))
        }
        .onClick(() => {
          this.showTypeSheet = true
        })
        .bindSheet($$this.showTypeSheet, this.TypeSheetBuilder, {
          title: { title: '选择阶段' },
          backgroundColor: $r('app.color.white'),
          height: 400
        })

2)完成选择单词分类交互,切换后关闭弹窗+回到顶部

ts
          Button() {
            Text(key)
              .fontSize(14)
              .fontColor(key === this.wordKey ? $r('app.color.common_green') : $r('app.color.common_gray_01'))
          }
          .backgroundColor($r('app.color.common_gray_bg'))
          .padding({ top: 6, right: 12, bottom: 6, left: 12 })
          .margin({ right: 12, bottom: 12 })
          .onClick(() => {
            this.wordKey = key
            this.showTypeSheet = false
            this.scroller.scrollTo({ yOffset: 0, xOffset: 0 })
          })
ts
  scroller = new Scroller()
  // ...
  List({ scroller: this.scroller }) {

示例代码半模态框

1)准备代码弹出

ts
  @State currentCode: string = ''

  webController = new webview.WebviewController()
ts
@Builder
  CodeSheetBuilder() {
    Column() {
      Web({ src: $rawfile('word.html'), controller: this.webController })
        .width('100%')
        .height(400)
        .backgroundColor($r('app.color.common_gray_bg'))
        .onPageEnd(() => {
          this.webController.runJavaScript(`writeHtml(\`${this.currentCode}\`)`)
        })
    }
    .padding({ left: 16, right: 16, top: 8, bottom: 34 })
  }

2)绑定和现实代码半模态框

ts
@State showCodeSheet: boolean = false
ts
    .width('100%')
    .height('100%')
    .bindSheet($$this.showCodeSheet, this.CodeSheetBuilder, {
      detents: [SheetSize.FIT_CONTENT],
      backgroundColor: $r('app.color.white'),
      title: { title: '详细代码' }
    })

3)点击代码

ts
Row() {
                Text('详细代码')
                  .fontSize(12)
                  .fontColor(item.code ? $r('app.color.common_gray_01') : '#dddddd')
                Image($r('sys.media.ohos_ic_public_arrow_right'))
                  .width(16)
                  .aspectRatio(1)
                  .fillColor(item.code ? $r('app.color.common_gray_01'): '#dddddd')
              }
              .alignSelf(ItemAlign.End)
              .onClick(() => {
                this.currentCode = item.code
                if (this.currentCode) {
                  this.showCodeSheet = true
                } else {
                  promptAction.showToast({ message: '暂无代码' })
                }
              })

单词朗读 Dialog

1)准备静态的 Dialog 组件 views/Word/WordDialog.ets

ts
@CustomDialog
export struct WordDialog {
  controller: CustomDialogController
  @Prop en: string = ''
  @Prop zh: string = ''

  build() {
    Column({ space: 10 }) {
      Row({ space: 10 }) {
        Text(this.en)
          .fontSize(20)
          .fontColor($r('app.color.white'))
          .fontWeight(500)
        WordSoundComp()
      }

      Text(this.zh)
        .fontColor($r('app.color.white'))
    }
    .constraintSize({ minWidth: 175 })
    .padding({ left: 16, right: 16 })
    .height(90)
    .borderRadius(45)
    .backgroundColor('#8f000000')
    .justifyContent(FlexAlign.Center)
  }
}

@Component
struct WordSoundComp {
  @State flag: boolean = false
  timerId?: number

  aboutToAppear(): void {
    this.timerId = setInterval(() => {
      this.flag = !this.flag
    }, 500)
  }

  aboutToDisappear(): void {
    clearInterval(this.timerId)
  }

  build() {
    Image($r('sys.media.ohos_ic_public_sound'))
      .width(20)
      .aspectRatio(1)
      .fillColor(this.flag ? $r('app.color.common_green') : $r('app.color.white'))
  }
}

2)打开 Dialog pages/WordPage.ets

ts
  @State currentEn: string = ''
  @State currentZh: string = ''
  dialog = new CustomDialogController({
    builder: WordDialog({ en: this.currentEn, zh: this.currentZh }),
    customStyle: true,
    alignment: DialogAlignment.Center
  })
ts
              Image($r('sys.media.ohos_ic_public_sound'))
                .width(20)
                .aspectRatio(1)
                .alignSelf(ItemAlign.Start)
                .fillColor($r('app.color.common_gray_03'))
                .onClick(() => {
                  this.currentEn = item.en
                  this.currentZh = item.zh
                  this.dialog.open()
                })

使用 AvPlayer 实现朗读

目标:了解如何播放网络音频

准备知识:

  • AvPlayer 播放管理类,用于管理和播放媒体资源。
  • AVPlayerState 播放的全流程包含:创建AVPlayer,设置播放资源,设置播放参数(音量/倍速/焦点模式),播放控制(播放/暂停/跳转/停止),重置,销毁资源。

alt text

落地代码:

views/Word/WordDialog.ets

ts

  avPlayer?: media.AVPlayer

  async aboutToAppear() {
    const avPlayer = await media.createAVPlayer()
    avPlayer.on('stateChange', state => {
      if (state === 'initialized') {
        avPlayer.prepare()
      } else if ( state === 'prepared') {
        avPlayer.loop = true
        avPlayer.play()
      }
    })
    avPlayer.url = `https://dict.youdao.com/dictvoice?type=1&audio=${this.en}`
    this.avPlayer = avPlayer
  }

  aboutToDisappear(): void {
    if (this.avPlayer) {
      this.avPlayer.stop()
      this.avPlayer.release()
    }
  }

Released under the Apache-2.0 License.