Reputation: 282
I have a modalBottomSheet. On it, I am displaying several widgets, especially an audioPlayer.
I have find out that when I press the play button, the audio file is playing, so far so good, but if I tap outside the modalBottomSheet, the modal is dismissed. I am OK to get the modal dismissed. But my problem is that when it is dismissed, the player which is running, is generating an exception.
Unhandled Exception: setState() called after dispose()
I do not want to make the Modal not dissmisible. Please, can you advise? Many thanks.
import 'package:audioplayers/audioplayers.dart';
import 'package:audioplayers/audioplayers_api.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:gtd_official_sharped_focused/Reusable%20Widget/Player_Audio/widgets/play_pause_button.dart';
class AudioPlayerWidget extends StatefulWidget {
final String url;
final bool isAsset;
final Duration currentTime;
final Duration totalTime;
final ValueChanged<Duration> onSeekBarMoved;
const AudioPlayerWidget({
Key key,
this.url,
this.isAsset = false,
this.currentTime,
this.totalTime,
this.onSeekBarMoved,
}) : super(key: key);
@override
_AudioPlayerWidgetState createState() => _AudioPlayerWidgetState();
}
class _AudioPlayerWidgetState extends State<AudioPlayerWidget> {
AudioPlayer _audioPlayer;
AudioCache _audioCache;
//variables for slider
Duration _duration = new Duration();
Duration _position = new Duration();
PlayerState _playerState = PlayerState.STOPPED;
bool get _isPlaying => _playerState == PlayerState.PLAYING;
bool get _isLocal => !widget.url.contains('https');
@override
void initState() {
_audioPlayer = AudioPlayer(mode: PlayerMode.MEDIA_PLAYER);
_audioCache = AudioCache(fixedPlayer: _audioPlayer);
_audioPlayer.onDurationChanged.listen((d) {setState(() {
_duration = d;
});});
_audioPlayer.onAudioPositionChanged.listen((p) {setState((){
_position = p;
});});
_audioPlayer.onPlayerCompletion.listen((event) {
setState(() {
_position = Duration(seconds: 0);
_playerState = PlayerState.STOPPED;
});
});
_audioPlayer.onPlayerError.listen((msg) {
print('audioPlayer error : $msg');
setState(() {
_playerState = PlayerState.STOPPED;
});
});
super.initState();
}
@override
void dispose() {
_audioPlayer.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Padding(
padding: const EdgeInsets.only(left:18.0),
child: Text(_position.toString().split('.')[0],style:TextStyle(fontSize: 16)),
),
Padding(
padding: const EdgeInsets.only(right:18.0),
child: Text(_duration.toString().split('.')[0],style:TextStyle(fontSize: 16)),
),
],),
_buildSliderBar(context),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
buttonBackWard10Seconds(),
PlayPauseButton(
isPlaying: _isPlaying,
onPlay: () => _playPause()
),
buttonForward10Seconds(),
//Do not delete iconButton below => for reference
/* IconButton(
onPressed: () => _stop(),
icon: Icon(
Icons.stop,
size: 40,
color: Colors.red,
),
),*/
],
),
],
);
}
//########################################################
_playPause() async {
if (_playerState == PlayerState.PLAYING) {
final playerResult = await _audioPlayer.pause();
if (playerResult == 1) {
setState(() {
_playerState = PlayerState.PAUSED;
});
}
} else if (_playerState == PlayerState.PAUSED) {
final playerResult = await _audioPlayer.resume();
if (playerResult == 1) {
setState(() {
_playerState = PlayerState.PLAYING;
});
}
} else {
if (widget.isAsset) {
_audioPlayer = await _audioCache.play(widget.url);
setState(() {
_playerState = PlayerState.PLAYING;
});
} else {
final playerResult = await _audioPlayer.play(widget.url, isLocal: _isLocal);
if (playerResult == 1) {
setState(() {
_playerState = PlayerState.PLAYING;
});
}
}
}
}
void changeToSecond(int second){
Duration newDuration = Duration(seconds:second);
_audioPlayer.seek(newDuration);
}
_stop() async {
final playerResult = await _audioPlayer.stop();
if (playerResult == 1) {
setState(() {
_playerState = PlayerState.STOPPED;
});
}
}
//###############################################################
Slider _buildSliderBar(BuildContext context) {
return Slider(
value: _position.inSeconds.toDouble(),
min: 0.0,
max: _duration.inSeconds.toDouble(), //_sliderValue,
activeColor: Colors.red,
inactiveColor: Colors.grey,
onChanged: (double value) {
setState(() {
changeToSecond(value.toInt());
value=value;
});
},
);
}
Widget buttonBackWard10Seconds(){
return IconButton( icon: Icon(CupertinoIcons.gobackward_10),
iconSize: 40,
color: Colors.black,
onPressed: (){
_position = _position - Duration(seconds:10);
if (_position < Duration(seconds:0)) {
_audioPlayer.seek(Duration(seconds: 0));
}
else {
_audioPlayer.seek(_position);
}});
}
Widget buttonForward10Seconds(){
return IconButton( icon:Icon( CupertinoIcons.goforward_10),
iconSize: 40,
color: Colors.black,
onPressed: (){
_position = _position + Duration(seconds:10);
if (_duration >_position) {
_audioPlayer.seek(_position);
}
else if (_duration <_position) {
_audioPlayer.seek(_duration);
}
}
);
}
}
import 'package:flutter/material.dart';
import 'package:gtd_official_sharped_focused/Reusable%20Widget/Player_Audio/widgets/audio_player_widget.dart';
import 'package:gtd_official_sharped_focused/Services/extract_file_Name_url/extract_file_name_url.dart';
Widget modalBottomPlayAudio (context,String urlToPlay){
showModalBottomSheet(
context: context,
//background color for modal bottom screen
backgroundColor: Colors.white,
//elevates modal bottom screen
elevation: 10,
// gives rounded corner to modal bottom screen
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
builder: (BuildContext context) {
// UDE : SizedBox instead of Container for whitespaces
return SizedBox(
height: 350,
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
/*Padding(
padding: const EdgeInsets.all(28.0),
),*/
Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Padding(
padding: const EdgeInsets.only(left:18.0),
child: Text(getFileNameFromURL(urlToPlay),
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold),),
),
],
),
SizedBox(height: 60,),
AudioPlayerWidget(url:urlToPlay),
],
),
),
);
},
);
}
Upvotes: 0
Views: 78
Reputation: 24940
you could change
setState(()=>{
...
})
to
if(mounted)(
setState(()=>{
...
})
)
Which ensures setState
is called only when the widget is mounted on the screen.
Upvotes: 1