Laurent Thomas
Laurent Thomas

Reputation: 282

Unhandled Exception: setState() called after dispose() - due to modal dissmissed

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

Answers (1)

krishnaacharyaa
krishnaacharyaa

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

Related Questions