Flutter中点击色块时停止当前音频,播放新音频终止旧音频
Flutter木琴音频播放冲突解决(audioplayers: ^0.19.0)
问题描述
我用audioplayers: ^0.19.0开发Flutter木琴应用,现有代码如下:
import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:audioplayers/src/audio_cache.dart'; void main() => runApp(XylophoneApp()); final player = AudioCache(); class XylophoneApp extends StatelessWidget { void playSound(String soundNumber) { player.play('beerpour.mp3'); } Expanded buildKey({required Color color, required String soundNumber}) { return Expanded( child: FlatButton( color: color, onPressed: () { // create a new player // Audio cache is for local assets if (color == Colors.red) { playSound(soundNumber);//here it is played when tapped,I want no currently running sound to stop when new sound is played. } else { //I want to stop when other is pressed. } }, child: Text( '', ), ), ); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( backgroundColor: Colors.black, body: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ buildKey(color: Colors.red, soundNumber: 'beerpour.mp3'), buildKey(color: Colors.green, soundNumber: 'beerpour.mp3'), buildKey(color: Colors.blue, soundNumber: 'beerpour.mp3'), buildKey(color: Colors.teal, soundNumber: 'beerpour.mp3'), buildKey(color: Colors.orange, soundNumber: 'beerpour.mp3'), buildKey(color: Colors.purple, soundNumber: 'beerpour.mp3'), buildKey(color: Colors.yellow, soundNumber: 'beerpour.mp3'), ], ), ), ), ); } }
需求:点击任意色块时,若当前有音频播放则停止;播放新音频时自动终止正在播放的音频。请问如何实现该功能?是否有更易实现的audioplayers版本?
解决方案
一、基于audioplayers: ^0.19.0的实现方法
^0.19.0版本中AudioCache每次调用play都会生成新的AudioPlayer实例,要实现停止当前播放的逻辑,需要保存当前播放的实例引用,每次点击时先终止它,再播放新音频:
- 将
XylophoneApp改为StatefulWidget,用于维护当前播放的播放器状态; - 声明
AudioPlayer? _currentPlayer变量存储当前播放实例; - 修改
playSound方法,先停止当前播放,再启动新音频并保存实例; - 移除原代码中按颜色区分的逻辑,所有色块执行统一的停止+播放流程。
修改后的完整代码:
import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:audioplayers/src/audio_cache.dart'; void main() => runApp(XylophoneApp()); class XylophoneApp extends StatefulWidget { @override _XylophoneAppState createState() => _XylophoneAppState(); } class _XylophoneAppState extends State<XylophoneApp> { final AudioCache _audioCache = AudioCache(); AudioPlayer? _currentPlayer; void playSound(String soundPath) async { // 停止当前正在播放的音频 if (_currentPlayer != null) { await _currentPlayer!.stop(); } // 播放新音频并保存播放器实例 _currentPlayer = await _audioCache.play(soundPath); } Expanded buildKey({required Color color, required String soundNumber}) { return Expanded( child: FlatButton( color: color, onPressed: () { playSound(soundNumber); }, child: Text(''), ), ); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( backgroundColor: Colors.black, body: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ buildKey(color: Colors.red, soundNumber: 'beerpour.mp3'), buildKey(color: Colors.green, soundNumber: 'beerpour.mp3'), buildKey(color: Colors.blue, soundNumber: 'beerpour.mp3'), buildKey(color: Colors.teal, soundNumber: 'beerpour.mp3'), buildKey(color: Colors.orange, soundNumber: 'beerpour.mp3'), buildKey(color: Colors.purple, soundNumber: 'beerpour.mp3'), buildKey(color: Colors.yellow, soundNumber: 'beerpour.mp3'), ], ), ), ), ); } }
二、更易实现的audioplayers版本推荐
推荐升级到**audioplayers: 1.0.0+**以上稳定版本(当前最新稳定版为5.x),新版本API更简洁,AudioCache已整合到AudioPlayer中,无需手动管理多个播放器实例:
- 直接使用
AudioPlayer加载本地资源,播放前调用stop()即可终止当前播放; - 无需导入
audio_cache.dart,API统一度更高。
示例代码(基于audioplayers: ^5.x):
import 'package:audioplayers/audioplayers.dart'; import 'package:flutter/material.dart'; void main() => runApp(const XylophoneApp()); class XylophoneApp extends StatefulWidget { const XylophoneApp({super.key}); @override State<XylophoneApp> createState() => _XylophoneAppState(); } class _XylophoneAppState extends State<XylophoneApp> { final AudioPlayer _player = AudioPlayer(); Future<void> playSound(String soundPath) async { // 先停止当前播放 await _player.stop(); // 加载并播放本地音频资源 await _player.play(AssetSource(soundPath)); } Expanded buildKey({required Color color, required String soundPath}) { return Expanded( child: TextButton( style: TextButton.styleFrom(backgroundColor: color), onPressed: () => playSound(soundPath), child: const Text(''), ), ); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( backgroundColor: Colors.black, body: SafeArea( child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ buildKey(color: Colors.red, soundPath: 'beerpour.mp3'), buildKey(color: Colors.green, soundPath: 'beerpour.mp3'), buildKey(color: Colors.blue, soundPath: 'beerpour.mp3'), buildKey(color: Colors.teal, soundPath: 'beerpour.mp3'), buildKey(color: Colors.orange, soundPath: 'beerpour.mp3'), buildKey(color: Colors.purple, soundPath: 'beerpour.mp3'), buildKey(color: Colors.yellow, soundPath: 'beerpour.mp3'), ], ), ), ), ); } }
新版本优势:
- API直观,无需区分
AudioCache与AudioPlayer; - 内置完善的播放控制方法,代码更简洁;
- 官方维护活跃,bug修复与功能更新及时。
内容的提问来源于stack exchange,提问作者bird
相关产品推荐
相关产品推荐

