音量变化监听过程中失效
===========

#### 问题现象

按照如下代码设置音量监听，运行过程中，突然会打印Destructor is successful，之后收不到音量变化监听事件。

registerVolumeChange() {
    let audioManager = audio.getAudioManager();
    let volumeManager = audioManager.getVolumeManager();
    volumeManager.on('streamVolumeChange', audio.StreamUsage.STREAM\_USAGE\_MUSIC,
      (streamVolumeEvent: audio.StreamVolumeEvent) => {
        console.info(\`StreamUsage of stream: ${streamVolumeEvent.streamUsage} \`);
        console.info(\`Volume level: ${streamVolumeEvent.volume} \`);
        console.info(\`Whether to updateUI: ${streamVolumeEvent.updateUi} \`);
      });
  }

#### 背景知识

*   在编程语言中，局部变量的作用域和生命周期是理解程序行为的关键概念之一。局部变量是在函数内部声明的变量，它们的作用域仅限于函数内部。这意味着局部变量只能在声明它们的函数内部被访问和使用。当函数被调用时，局部变量会被创建并分配内存。这些变量的生命周期与函数的执行周期紧密相关，即局部变量在函数执行期间存在，一旦函数执行结束，局部变量所占用的内存空间就会被释放。
*   管理系统音量的接口由audioVolumeManager提供，在使用之前，需要使用[getVolumeManager()](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-audio-audiomanager#getvolumemanager9)获取audioVolumeManager实例，可以通过设置监听事件来监听系统音量的变化，详情可以参考：[监听系统音量变化](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/volume-management#监听系统音量变化)。

#### 问题定位

检查日志发现打印了如下日志，说明audioVolumeManager已被销毁，需要分析代码确认VolumeManager被销毁的原因：

\[Destructor\]Destructor is successful.

检查代码发现audioVolumeManager变量在函数中就通过let进行了声明，这会导致函数执行结束后audioVolumeManager变量被释放，因此后续无法监听到音量变化。

#### 分析结论

audioVolumeManager在错误的地方进行了声明导致执行完函数后相应变量被释放，因此后续无法正常监听音量变化。

#### 修改建议

通过将audioVolumeManager和组件进行绑定，将volumeManager定义为组件的成员变量。在需要调用的地方，通过访问成员变量[监听系统音量变化](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/volume-management#监听系统音量变化)。

import {audio} from '@kit.AudioKit';

@Entry
@Component
struct Index{
  private audioManager = audio.getAudioManager();
  private volumeManager = this.audioManager.getVolumeManager();

  aboutToAppear(): void {
    this.registerVolumeChange();
  }
  build() {
    Column();
  }
  registerVolumeChange(){
    this.volumeManager.on('streamVolumeChange', audio.StreamUsage.STREAM\_USAGE\_MUSIC, (streamVolumeEvent: audio.StreamVolumeEvent) => {
      console.info(\`StreamUsage of stream: ${streamVolumeEvent.streamUsage} \`);
      console.info(\`Volume level: ${streamVolumeEvent.volume} \`);
      console.info(\`Whether to updateUI: ${streamVolumeEvent.updateUi} \`);
    });
  }
}

#### 总结

如果是需要长期使用的变量，不能在函数中进行声明，否则会使得函数结束时变量也被释放。

#### 常见FAQ

Q：如何不通过监听音量调节获取当前系统音量大小？

A：通过[AudioManager](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-audio-audiomanager)管理音频音量和音频设备，使用[getvolumebystream](https://developer.huawei.com/consumer/cn/doc/harmonyos-references/arkts-apis-audio-audiovolumemanager#getvolumebystream20)接口获取指定流的音量。