From 523864dd18878775b430d258c0b8a47db684dc46 Mon Sep 17 00:00:00 2001 From: wuqifeng <540416539@qq.com> Date: Tue, 16 Jul 2024 17:52:37 +0800 Subject: [PATCH] feat:音频播放单例增加声明周期感知 --- lib/pages/games/bloc.dart | 2 +- lib/pages/section/section_page.dart | 74 ++++++++++++++++++++++++++++++++++---------------------------------------- lib/utils/audio_player_util.dart | 52 ++++++++++++++++++++++++++++++++++++++-------------- 3 files changed, 73 insertions(+), 55 deletions(-) diff --git a/lib/pages/games/bloc.dart b/lib/pages/games/bloc.dart index 0efc369..632fc9a 100644 --- a/lib/pages/games/bloc.dart +++ b/lib/pages/games/bloc.dart @@ -44,7 +44,7 @@ class GamesBloc extends Bloc { } void _gotoGamePage(GotoGamePageEvent event, Emitter emit) async { - AudioPlayerUtil.getInstance().pause(); + await AudioPlayerUtil.getInstance().pause(); try { _methodChannel = const MethodChannel('wow_english/game_method_channel'); await _methodChannel diff --git a/lib/pages/section/section_page.dart b/lib/pages/section/section_page.dart index 38c69a2..2a31395 100644 --- a/lib/pages/section/section_page.dart +++ b/lib/pages/section/section_page.dart @@ -59,7 +59,7 @@ class _SectionPageView extends StatelessWidget { Widget build(BuildContext context) { final bloc = BlocProvider.of(context); return BlocListener( - listener: (context, state) { + listener: (context, state) async { if (state is RequestVideoLessonState) { final videoUrl = bloc.processEntity?.videos?.videoUrl ?? ''; var title = ''; @@ -103,40 +103,36 @@ class _SectionPageView extends StatelessWidget { ///视频类型 ///获取视频课程内容 if (state.courseType == 1) { - AudioPlayerUtil.getInstance() + await AudioPlayerUtil.getInstance() .playAudio(AudioPlayerUtilType.musicTime); } else { - AudioPlayerUtil.getInstance() + await AudioPlayerUtil.getInstance() .playAudio(AudioPlayerUtilType.videoTime); } - Future.delayed(const Duration(seconds: 1), () { - bloc.add(RequestVideoLessonEvent( - state.courseLessonId, state.courseType)); - }); + bloc.add(RequestVideoLessonEvent( + state.courseLessonId, state.courseType)); return; } if (state.courseType == SectionType.pictureBook.value) { - AudioPlayerUtil.getInstance() + await AudioPlayerUtil.getInstance() .playAudio(AudioPlayerUtilType.readingTime); - Future.delayed(const Duration(seconds: 1), () { - //绘本 - pushNamed(AppRouteName.reading, - arguments: {'courseLessonId': state.courseLessonId}) - .then((value) { - if (value != null) { - Map dataMap = value as Map; - bloc.add(RequestEndClassEvent( - dataMap['courseLessonId']!, - dataMap['isCompleted'], - currentStep: dataMap['currentStep'], - autoNextSection: dataMap['nextSection'], - )); - AudioPlayerUtil.getInstance() - .playAudio(AudioPlayerUtilType.countWithMe); - } - }); + //绘本 + pushNamed(AppRouteName.reading, + arguments: {'courseLessonId': state.courseLessonId}) + .then((value) { + if (value != null) { + Map dataMap = value as Map; + bloc.add(RequestEndClassEvent( + dataMap['courseLessonId']!, + dataMap['isCompleted'], + currentStep: dataMap['currentStep'], + autoNextSection: dataMap['nextSection'], + )); + AudioPlayerUtil.getInstance() + .playAudio(AudioPlayerUtilType.countWithMe); + } }); return; @@ -144,22 +140,20 @@ class _SectionPageView extends StatelessWidget { if (state.courseType == SectionType.practice.value) { //练习 - AudioPlayerUtil.getInstance() + await AudioPlayerUtil.getInstance() .playAudio(AudioPlayerUtilType.quizTime); - Future.delayed(const Duration(seconds: 1), () { - pushNamed(AppRouteName.topicPic, - arguments: {'courseLessonId': state.courseLessonId}) - .then((value) { - if (value != null) { - Map dataMap = value as Map; - bloc.add(RequestEndClassEvent( - dataMap['courseLessonId']!, dataMap['isCompleted'], - currentStep: dataMap['currentStep'], - autoNextSection: dataMap['nextSection'])); - } - AudioPlayerUtil.getInstance() - .playAudio(AudioPlayerUtilType.countWithMe); - }); + pushNamed(AppRouteName.topicPic, + arguments: {'courseLessonId': state.courseLessonId}) + .then((value) { + if (value != null) { + Map dataMap = value as Map; + bloc.add(RequestEndClassEvent( + dataMap['courseLessonId']!, dataMap['isCompleted'], + currentStep: dataMap['currentStep'], + autoNextSection: dataMap['nextSection'])); + } + AudioPlayerUtil.getInstance() + .playAudio(AudioPlayerUtilType.countWithMe); }); return; } diff --git a/lib/utils/audio_player_util.dart b/lib/utils/audio_player_util.dart index db913cf..be23cdf 100644 --- a/lib/utils/audio_player_util.dart +++ b/lib/utils/audio_player_util.dart @@ -1,4 +1,5 @@ import 'package:audioplayers/audioplayers.dart'; +import 'package:flutter/cupertino.dart'; import 'package:wow_english/common/extension/string_extension.dart'; enum AudioPlayerUtilType { @@ -18,15 +19,18 @@ enum AudioPlayerUtilType { final String path; } -class AudioPlayerUtil { +class AudioPlayerUtil extends WidgetsBindingObserver { static AudioPlayerUtil? _instance; - late AudioPlayer audioPlayer; + late AudioPlayer _audioPlayer; late AudioPlayerUtilType currentType; + bool _wasPlaying = false; // 私有构造函数 AudioPlayerUtil._internal() { - audioPlayer = AudioPlayer(); - audioPlayer.onPlayerStateChanged.listen((event) async { + // 监听应用生命周期 + WidgetsBinding.instance.addObserver(this); + _audioPlayer = AudioPlayer(); + _audioPlayer.onPlayerStateChanged.listen((event) async { if (event == PlayerState.completed) { // 播放结束再次播放 if (currentType == AudioPlayerUtilType.inMyTummy) { @@ -56,26 +60,46 @@ class AudioPlayerUtil { Future playAudio(AudioPlayerUtilType type) async { currentType = type; String path = type.path; - await audioPlayer.play(AssetSource(path.assetMp3), volume: 0.5); - await audioPlayer.onPlayerComplete.first; + await _audioPlayer.play(AssetSource(path.assetMp3), volume: 0.5); + await _audioPlayer.onPlayerComplete.first; } // stop - void stop() { - audioPlayer.stop(); + Future stop() async { + _audioPlayer.stop(); } // pause - void pause() { - if (audioPlayer.state == PlayerState.playing) { - audioPlayer.pause(); + Future pause() async { + if (_audioPlayer.state == PlayerState.playing) { + _audioPlayer.pause(); } } // resume - void resume() { - if (audioPlayer.state == PlayerState.paused) { - audioPlayer.resume(); + Future resume() async { + if (_audioPlayer.state == PlayerState.paused) { + _audioPlayer.resume(); } } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) async { + if (state == AppLifecycleState.paused) { + if (_audioPlayer.state == PlayerState.playing) { + _wasPlaying = true; + await pause(); + }; + } else if (state == AppLifecycleState.resumed) { + if (_wasPlaying == true) { + _wasPlaying = false; + await resume(); + } + } + } + + void dispose() { + _audioPlayer.dispose(); + WidgetsBinding.instance.removeObserver(this); + } } -- libgit2 0.22.2