Home > Software design >  I want to call images and audio lists in order using AudioPlayer()
I want to call images and audio lists in order using AudioPlayer()

Time:09-20

I'm going to make an app that plays a list of images and audio in order. After audio playback, the following images and audio are played. I update image to setState() when the playback is completed. And each time use setState(), I used play() function inside the build() method to recall play().

However, the method in the build is called twice, so the audio file is also played twice.

How do I run this method only once when I build it?

class PlayingScreen extends StatefulWidget {
  final PostModel postModel;

  PlayingScreen({
    Key? key,
    required this.postModel,
  }) : super(key: key);

  @override
  State<PlayingScreen> createState() => _PlayingScreenState();
}

class _PlayingScreenState extends State<PlayingScreen> {
  final _audioPlayer = AudioPlayer(); 
  List<String> _audios = []; // audio file path list
  int _playIndex = 0;

  @override
  void initState() {
    _getAudios();
    super.initState();
  }

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

  @override
  Widget build(BuildContext context) {
    _play(_playIndex);

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.postModel.title),
      ),
      body: InkWell(
        onTap: () {
          Get.back();
        },

       // image widget
        ),
      ),
    );
  }

  Future _play(int index) async {
    await _audioPlayer.play(DeviceFileSource(_audios[index]));
    logger.d("current index: $_playIndex / ${_audios.length - 1}");
    //complete event
    _audioPlayer.onPlayerComplete.listen((event) {
      logger.d("complet, next");
      setState(() {
        if (_playIndex >= _imageSets.length - 1) {
          _playIndex = 0;
          logger.d("return first index");
        } else {
          _playIndex  ;
        }
      });
    });
  }
}

CodePudding user response:

// ...
int _playIndex = 0;
bool played = false
// ...

// build
if(! played) {    
  _play(_playIndex);
  played = true;
}
  1. Add the variable "played" at the class level
  2. Add a check in the build method

CodePudding user response:

Calling a future inside the build method will always rebuild multiple times not only twice. I would probably use it in a FutureBuilder() like so:

FutureBuilder(
future:_play(_playIndex),
builder:(context, snapshot){
 ...
 }

)
  • Related