英文:
Freeze when playing URL with 'audioplayers' library in Flutter?
问题
以下是您提供的代码的翻译部分:
我有一组URL,我想在Flutter中使用'audioplayers'来播放。当URL列表开始播放时,播放7-8个URL后,冻结过程会发生。应用程序和页面会冻结。这总是显示为错误:
E/flutter (11570): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Bad state: Future already completed
E/flutter (11570): #0 _AsyncCompleter.complete (dart:async/future_impl.dart:35:31)
E/flutter (11570): #1 AudioPlayer._completePrepared.<anonymous closure> (package:audioplayers/src/audioplayer.dart:292:29)
E/flutter (11570): #2 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
E/flutter (11570): #3 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
E/flutter (11570): #4 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
E/flutter (11570): #5 _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11)
E/flutter (11570): #6 _MapStream._handleData (dart:async/stream_pipe.dart:218:10)
E/flutter (11570): #7 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
E/flutter (11570): #8 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
E/flutter (11570): #9 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
E/flutter (11570): #10 _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11)
E/flutter (11570): #11 _WhereStream._handleData (dart:async/stream_pipe.dart:195:12)
E/flutter (11570): #12 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
E/flutter (11570): #13 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
E/flutter (11570): #14 _DelayedData.perform (dart:async/stream_impl.dart:515:14)
E/flutter (11570): #15 _PendingEvents.handleNext (dart:async/stream_impl.dart:620:11)
E/flutter (11570): #16 _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:591:7)
E/flutter (11570): #17 _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter (11570): #18 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
我的相关代码如下:
bool isPlaying = false;
AudioPlayer audioPlayer = AudioPlayer();
int currentIndex = 0;
int start = 0;
//按钮按下
onPressed: () {
isPlaying = !isPlaying;
if (start == 0) {
start++;
playAudioInstructions();
} else if (start == 1) {
start++;
audioPlayer.pause();
} else {
start--;
audioPlayer.resume();
}
setState(() {});
},
void playAudioInstructions() {
playAudio(urlList, currentIndex);
}
Future<void> playAudio(List<String> urlList, int currentIndex) async {
await audioPlayer.play(UrlSource(urlList[currentIndex]));
audioPlayer.onPlayerComplete.listen((event) {
if (currentIndex < urlList.length - 1) {
audioPlayer.stop();
currentIndex++;
playAudio(urlList, currentIndex);
} else {
currentIndex = 0;
audioPlayer.stop();
start = 0;
}
});
}
我无法找出冻结的原因。我将很乐意帮助您调整代码片段。
英文:
I have a list of URLs that I want to play with 'audioplayers' in Flutter. When the URL list starts to play, the freezing process occurs after playing 7-8 URLs. App and page freezes. This is always shown as an error:
E/flutter (11570): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Bad state: Future already completed
E/flutter (11570): #0 _AsyncCompleter.complete (dart:async/future_impl.dart:35:31)
E/flutter (11570): #1 AudioPlayer._completePrepared.<anonymous closure> (package:audioplayers/src/audioplayer.dart:292:29)
E/flutter (11570): #2 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
E/flutter (11570): #3 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
E/flutter (11570): #4 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
E/flutter (11570): #5 _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11)
E/flutter (11570): #6 _MapStream._handleData (dart:async/stream_pipe.dart:218:10)
E/flutter (11570): #7 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
E/flutter (11570): #8 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
E/flutter (11570): #9 _BufferingStreamSubscription._add (dart:async/stream_impl.dart:271:7)
E/flutter (11570): #10 _ForwardingStreamSubscription._add (dart:async/stream_pipe.dart:123:11)
E/flutter (11570): #11 _WhereStream._handleData (dart:async/stream_pipe.dart:195:12)
E/flutter (11570): #12 _RootZone.runUnaryGuarded (dart:async/zone.dart:1594:10)
E/flutter (11570): #13 _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:339:11)
E/flutter (11570): #14 _DelayedData.perform (dart:async/stream_impl.dart:515:14)
E/flutter (11570): #15 _PendingEvents.handleNext (dart:async/stream_impl.dart:620:11)
E/flutter (11570): #16 _PendingEvents.schedule.<anonymous closure> (dart:async/stream_impl.dart:591:7)
E/flutter (11570): #17 _microtaskLoop (dart:async/schedule_microtask.dart:40:21)
E/flutter (11570): #18 _startMicrotaskLoop (dart:async/schedule_microtask.dart:49:5)
My related codes are as follows:
bool isPlaying = false;
AudioPlayer audioPlayer = AudioPlayer();
int currentIndex = 0;
int start = 0;
...
//button pressed
onPressed: () {
isPlaying = !isPlaying;
if (start == 0) {
start++;
playAudioInstructions();
} else if (start == 1) {
start++;
audioPlayer.pause();
} else {
start--;
audioPlayer.resume();
}
setState(() {});
},
...
void playAudioInstructions() {
playAudio(urlList, currentIndex);
}
Future<void> playAudio(List<String> urlList, int currentIndex) async {
await audioPlayer.play(UrlSource(urlList[currentIndex]));
audioPlayer.onPlayerComplete.listen((event) {
if (currentIndex < urlList.length - 1) {
audioPlayer.stop();
currentIndex++;
playAudio(urlList, currentIndex);
} else {
currentIndex = 0;
audioPlayer.stop();
start = 0;
}
});
}
...
I couldn't figure out the cause of the freezing. I'd be happy to get help with the code snippet.
答案1
得分: -2
你遇到的冻结问题似乎与你的Flutter应用中的“坏状态:Future已经完成”错误有关。通常情况下,当你尝试完成已经完成的Future时,会发生这个错误。
从你的代码来看,问题似乎发生在playAudio函数中,当你递归调用playAudio以播放列表中的下一个URL时。问题出现在你在创建新订阅之前未正确取消先前的audioPlayer.onPlayerComplete订阅。结果是会创建多个订阅,导致错误发生。
要解决这个问题,你需要在创建新订阅之前使用cancel方法取消先前的订阅。以下是你的代码的更新版本,包括必要的修改:
bool isPlaying = false;
AudioPlayer audioPlayer = AudioPlayer();
int currentIndex = 0;
int start = 0;
StreamSubscription<void>? playerCompleteSubscription; // Add this line
// ...
onPressed: () {
isPlaying = !isPlaying;
if (start == 0) {
start++;
playAudioInstructions();
} else if (start == 1) {
start++;
audioPlayer.pause();
} else {
start--;
audioPlayer.resume();
}
setState(() {});
},
// ...
void playAudioInstructions() {
playAudio(urlList, currentIndex);
}
Future<void> playAudio(List<String> urlList, int currentIndex) async {
await audioPlayer.play(UrlSource(urlList[currentIndex]));
playerCompleteSubscription?.cancel(); // Cancel previous subscription if exists
playerCompleteSubscription = audioPlayer.onPlayerComplete.listen((event) {
if (currentIndex < urlList.length - 1) {
audioPlayer.stop();
currentIndex++;
playAudio(urlList, currentIndex);
} else {
currentIndex = 0;
audioPlayer.stop();
start = 0;
}
});
}
在更新后的代码中,我添加了一个StreamSubscription
通过取消先前的订阅,你确保一次只有一个订阅处于活动状态,防止了“坏状态:Future已经完成”错误和潜在的应用程序冻结。
请确保用上述修改后的代码替换你原始代码中的相应部分。
英文:
The freezing issue you're experiencing seems to be related to the "Bad state: Future already completed" error in your Flutter app. This error typically occurs when you try to complete a Future that has already been completed.
Looking at your code, the issue seems to be happening in the playAudio function when you recursively call playAudio to play the next URL in the list. The problem arises because you're not properly canceling the previous audioPlayer.onPlayerComplete subscription before creating a new one. As a result, multiple subscriptions are created, leading to the error.
To fix this issue, you need to cancel the previous subscription using the cancel method before creating a new subscription. Here's an updated version of your code with the necessary modifications:
bool isPlaying = false;
AudioPlayer audioPlayer = AudioPlayer();
int currentIndex = 0;
int start = 0;
StreamSubscription<void>? playerCompleteSubscription; // Add this line
// ...
onPressed: () {
isPlaying = !isPlaying;
if (start == 0) {
start++;
playAudioInstructions();
} else if (start == 1) {
start++;
audioPlayer.pause();
} else {
start--;
audioPlayer.resume();
}
setState(() {});
},
// ...
void playAudioInstructions() {
playAudio(urlList, currentIndex);
}
Future<void> playAudio(List<String> urlList, int currentIndex) async {
await audioPlayer.play(UrlSource(urlList[currentIndex]));
playerCompleteSubscription?.cancel(); // Cancel previous subscription if exists
playerCompleteSubscription = audioPlayer.onPlayerComplete.listen((event) {
if (currentIndex < urlList.length - 1) {
audioPlayer.stop();
currentIndex++;
playAudio(urlList, currentIndex);
} else {
currentIndex = 0;
audioPlayer.stop();
start = 0;
}
});
}
In the updated code, I added a StreamSubscription<void>? playerCompleteSubscription variable to keep track of the subscription for audioPlayer.onPlayerComplete events. Before creating a new subscription, I check if there is an existing subscription and cancel it using the cancel method.
By canceling the previous subscription, you ensure that only one subscription is active at a time, preventing the "Bad state: Future already completed" error and potential freezing of the app.
Make sure to replace the corresponding sections in your original code with the modified code provided above.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论