长笛和音频播放器:不能在两个课程之间停止播放音频



**你好,

我是Flutter的新手,我希望你能理解我的问题。我正在使用"AudioPlayers",希望播放定义页面和类中的音频,并能够停止同一页面中另一个类中的音乐。在我的代码中,如果我呆在同一个类中,一切都正常,但一旦音频启动,我切换到另一个类(通过链接),音频就会继续播放,并且STOP按钮不起作用。这是我的代码,我对此进行了一些解释。

共有3个类别:

注意:多亏了appbar,我们可以看到我们在哪个类。

第1类:2个按钮,播放/暂停和停止这门课效果很好。当我点击"停止"时,音频停止,我们进入第2课。

第2类:2个按钮,播放/暂停和";至类别3";播放/暂停按钮工作良好;至类别3";它也能工作,音频一直在播放,这也是我想要的,到目前为止还不错。

class 3=2个按钮,播放/暂停和停止。问题是停止按钮不起作用。它并没有阻止奥迪从Class2 推出

我能看到的是:

  • 只要按钮在同一类中,它们就可以工作
  • 即使在更改类别后,音频仍会继续播放
  • 停止按钮仅适用于在其自己的类上启动的音频。如果音频是在另一个类上启动的,则停止按钮不起作用

你能帮我解决这个问题吗?

如果你也有这种可能性,那就不那么重要了:例如,当我在第1类时,我点击停止按钮,音频停止,我切换到第2类,第2类音频自动启动,而不必点击播放按钮。

提前感谢您的帮助。

以下是完整的代码:**

import 'dart:typed_data';
import 'package:audioplayers/audioplayers.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class Class1 extends  StatefulWidget {
@override
State<Class1> createState() => _Class1State();
}
class _Class1State extends State<Class1> {
int maxduration = 100;
int currentpos = 0;
String currentpostlabel = "00:00";
String audioasset = "assets/audio/audio1.mp3";
bool isplaying = false;
bool audioplayed = false;
late Uint8List audiobytes;

AudioPlayer player = AudioPlayer();
@override
void initState() {
Future.delayed(Duration.zero, () async {
ByteData bytes = await rootBundle.load(audioasset); //load audio from assets
audiobytes = bytes.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes);
//convert ByteData to Uint8List
player.onDurationChanged.listen((Duration d) { //get the duration of audio
maxduration = d.inMilliseconds;
setState(() {
});
});
player.onAudioPositionChanged.listen((Duration  p){
currentpos = p.inMilliseconds; //get the current position of playing audio
//generating the duration label
int shours = Duration(milliseconds:currentpos).inHours;
int sminutes = Duration(milliseconds:currentpos).inMinutes;
int sseconds = Duration(milliseconds:currentpos).inSeconds;
int rhours = shours;
int rminutes = sminutes - (shours * 60);
int rseconds = sseconds - (sminutes * 60 + shours * 60 * 60);
currentpostlabel = "$rhours:$rminutes:$rseconds";
setState(() {
//refresh the UI
});
});
});
super.initState();

}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Class1"),
backgroundColor: Colors.blue
),
body: Container(
margin: EdgeInsets.only(top:50),
child: Column(
children: [
Container(
child: Wrap(
spacing: 10,
children: [
ElevatedButton.icon(
onPressed: () async {
if(!isplaying && !audioplayed){
int result = await player.playBytes(audiobytes);
if(result == 1){ //play success
setState(() {
isplaying = true;
audioplayed = true;
});
}else{
print("Error while playing audio.");
}
}else if(audioplayed && !isplaying){
int result = await player.resume();
if(result == 1){ //resume success
setState(() {
isplaying = true;
audioplayed = true;
});
}else{
print("Error on resume audio.");
}
}else{
int result = await player.pause();
if(result == 1){ //pause success
setState(() {
isplaying = false;
});
}else{
print("Error on pause audio.");
}
}
},
icon: Icon(isplaying?Icons.pause:Icons.play_arrow),
label:Text(isplaying?"Pause":"Play")
),
ElevatedButton.icon(
onPressed: ()  {
setState(() {
Navigator.pushReplacement(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => Class2(),
transitionDuration: Duration.zero,
)
);
});
setState(() async {
int result = await player.stop();
if(result == 1){ //stop success
setState(() {
isplaying = false;
audioplayed = false;
currentpos = 0;
});
}else{
print("Error on stop audio.");
}
});
},
icon: Icon(Icons.stop),
label:Text("Stop")
),

],
),
)
],
)
)
);
}
}




class Class2 extends  StatefulWidget {
@override
State<Class2> createState() => _Class2State();
}
class _Class2State extends State<Class2> {
int maxduration = 100;
int currentpos = 0;
String currentpostlabel = "00:00";
String audioasset = "assets/audio/audio2.mp3";
bool isplaying = false;
bool audioplayed = false;
late Uint8List audiobytes;

AudioPlayer player = AudioPlayer();
@override
void initState() {
Future.delayed(Duration.zero, () async {
ByteData bytes = await rootBundle.load(audioasset); //load audio from assets
audiobytes = bytes.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes);
//convert ByteData to Uint8List
player.onDurationChanged.listen((Duration d) { //get the duration of audio
maxduration = d.inMilliseconds;
setState(() {
});
});
player.onAudioPositionChanged.listen((Duration  p){
currentpos = p.inMilliseconds; //get the current position of playing audio
//generating the duration label
int shours = Duration(milliseconds:currentpos).inHours;
int sminutes = Duration(milliseconds:currentpos).inMinutes;
int sseconds = Duration(milliseconds:currentpos).inSeconds;
int rhours = shours;
int rminutes = sminutes - (shours * 60);
int rseconds = sseconds - (sminutes * 60 + shours * 60 * 60);
currentpostlabel = "$rhours:$rminutes:$rseconds";
setState(() {
//refresh the UI
});
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Class2"),
backgroundColor: Colors.blueAccent
),
body: Container(
margin: EdgeInsets.only(top:50),
child: Column(
children: [

Container(
child: Wrap(
spacing: 10,
children: [
ElevatedButton.icon(
onPressed: () async {
if(!isplaying && !audioplayed){
int result = await player.playBytes(audiobytes);
if(result == 1){ //play success
setState(() {
isplaying = true;
audioplayed = true;
});
}else{
print("Error while playing audio.");
}
}else if(audioplayed && !isplaying){
int result = await player.resume();
if(result == 1){ //resume success
setState(() {
isplaying = true;
audioplayed = true;
});
}else{
print("Error on resume audio.");
}
}else{
int result = await player.pause();
if(result == 1){ //pause success
setState(() {
isplaying = false;
});
}else{
print("Error on pause audio.");
}
}
},
icon: Icon(isplaying?Icons.pause:Icons.play_arrow),
label:Text(isplaying?"Pause":"Play")
),
ElevatedButton.icon(
onPressed: ()  {
setState(() {
Navigator.pushReplacement(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => Class3(),
transitionDuration: Duration.zero,
)
);
});

},
icon: Icon(Icons.stop),
label:Text("To Class3")
),

],
),
)
],
)
)
);
}


}


class Class3 extends  StatefulWidget {
@override
State<Class3> createState() => _Class3State();
}
class _Class3State extends State<Class3> {
int maxduration = 100;
int currentpos = 0;
String currentpostlabel = "00:00";
String audioasset = "assets/audio/audio3.mp3";
bool isplaying = false;
bool audioplayed = false;
late Uint8List audiobytes;

AudioPlayer player = AudioPlayer();

@override
void initState() {
Future.delayed(Duration.zero, () async {
ByteData bytes = await rootBundle.load(audioasset); //load audio from assets
audiobytes = bytes.buffer.asUint8List(bytes.offsetInBytes, bytes.lengthInBytes);
//convert ByteData to Uint8List
player.onDurationChanged.listen((Duration d) { //get the duration of audio
maxduration = d.inMilliseconds;
setState(() {
});
});
player.onAudioPositionChanged.listen((Duration  p){
currentpos = p.inMilliseconds; //get the current position of playing audio
//generating the duration label
int shours = Duration(milliseconds:currentpos).inHours;
int sminutes = Duration(milliseconds:currentpos).inMinutes;
int sseconds = Duration(milliseconds:currentpos).inSeconds;
int rhours = shours;
int rminutes = sminutes - (shours * 60);
int rseconds = sseconds - (sminutes * 60 + shours * 60 * 60);
currentpostlabel = "$rhours:$rminutes:$rseconds";
setState(() {
//refresh the UI
});
});
});
super.initState();

}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Class3"),
backgroundColor: Colors.blueGrey
),
body: Container(
margin: EdgeInsets.only(top:50),
child: Column(
children: [
Container(
child: Wrap(
spacing: 10,
children: [
ElevatedButton.icon(
onPressed: () async {
if(!isplaying && !audioplayed){
int result = await player.playBytes(audiobytes);
if(result == 1){ //play success
setState(() {
isplaying = true;
audioplayed = true;
});
}else{
print("Error while playing audio.");
}
}else if(audioplayed && !isplaying){
int result = await player.resume();
if(result == 1){ //resume success
setState(() {
isplaying = true;
audioplayed = true;
});
}else{
print("Error on resume audio.");
}
}else{
int result = await player.pause();
if(result == 1){ //pause success
setState(() {
isplaying = false;
});
}else{
print("Error on pause audio.");
}
}
},
icon: Icon(isplaying?Icons.pause:Icons.play_arrow),
label:Text(isplaying?"Pause":"Play")
),

ElevatedButton.icon(
onPressed: ()  {
setState(() async {
int result = await player.stop();
if(result == 1){ //stop success
setState(() {
isplaying = false;
audioplayed = false;
currentpos = 0;
});
}else{
print("Error on stop audio.");
}
});

},
icon: Icon(Icons.stop),
label:Text("Stop")
),

],
),
)
],
)
)
);
}


}

我认为停止按钮不起作用的原因是每个类都有自己的AudioPlayer实例。这意味着他们无法与之前的职业玩家互动,以及为什么停止按钮不起作用。

有几种方法可以解决这个问题。然而,看看示例中的代码,有很多重复的代码,不确定为什么需要三个类(没有完全阅读所有的代码行)。一种解决方案是将AudioPlayer及其功能分离到自己的类中,并在每个类中管理其状态。本质上只有一个AudioPlayer实例,所有类都可以在其中进行交互。

我不太确定您想要在class3中实现什么。对于每个类,您都有彼此独立的音频播放器对象。因此,他们的行为完全独立。我假设当你切换类时,音频仍在播放,因为你没有调用来处理它。

@override
void dispose() {
player.dispose();
super.dispose();
}

除此之外,如果你想停止从另一个类开始的音频,你应该将对象传递给其他类并使用它

class Class3 extends  StatefulWidget {
final AudioPlayer player;
const Class3 ({
required this.player,
Key? key
}) : super(key: key);
@override
State<Class3> createState() => _Class3State();
}

在切换类别时:

Navigator.pushReplacement(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => Class3(player),
....

因此,这将把音频播放器从类2传递到类3,因此,它可以从类3停止。

最新更新