Commit 8fb5f8606a35fb4b298ad45468c9e3c205f52122
1 parent
d100908a
feat:先声录音状态优化
Showing
4 changed files
with
32 additions
and
45 deletions
lib/pages/practice/bloc/topic_picture_bloc.dart
| @@ -26,20 +26,6 @@ part 'topic_picture_event.dart'; | @@ -26,20 +26,6 @@ part 'topic_picture_event.dart'; | ||
| 26 | 26 | ||
| 27 | part 'topic_picture_state.dart'; | 27 | part 'topic_picture_state.dart'; | 
| 28 | 28 | ||
| 29 | -enum VoicePlayState { | ||
| 30 | - ///未知 | ||
| 31 | - unKnow, | ||
| 32 | - | ||
| 33 | - ///播放中 | ||
| 34 | - playing, | ||
| 35 | - | ||
| 36 | - ///播放完成 | ||
| 37 | - completed, | ||
| 38 | - | ||
| 39 | - ///播放终止 | ||
| 40 | - stop | ||
| 41 | -} | ||
| 42 | - | ||
| 43 | class TopicPictureBloc | 29 | class TopicPictureBloc | 
| 44 | extends BaseSectionBloc<TopicPictureEvent, TopicPictureState> with WidgetsBindingObserver { | 30 | extends BaseSectionBloc<TopicPictureEvent, TopicPictureState> with WidgetsBindingObserver { | 
| 45 | final PageController pageController; | 31 | final PageController pageController; | 
| @@ -57,9 +43,6 @@ class TopicPictureBloc | @@ -57,9 +43,6 @@ class TopicPictureBloc | ||
| 57 | ///正在评测 | 43 | ///正在评测 | 
| 58 | bool _isRecording = false; | 44 | bool _isRecording = false; | 
| 59 | 45 | ||
| 60 | - ///正在播放音频 | ||
| 61 | - VoicePlayState _voicePlayState = VoicePlayState.unKnow; | ||
| 62 | - | ||
| 63 | int get currentPage => _currentPage + 1; | 46 | int get currentPage => _currentPage + 1; | 
| 64 | 47 | ||
| 65 | /// 选择题选中项 | 48 | /// 选择题选中项 | 
| @@ -67,8 +50,6 @@ class TopicPictureBloc | @@ -67,8 +50,6 @@ class TopicPictureBloc | ||
| 67 | 50 | ||
| 68 | bool get isRecording => _isRecording; | 51 | bool get isRecording => _isRecording; | 
| 69 | 52 | ||
| 70 | - VoicePlayState get voicePlayState => _voicePlayState; | ||
| 71 | - | ||
| 72 | late MethodChannel methodChannel; | 53 | late MethodChannel methodChannel; | 
| 73 | 54 | ||
| 74 | late AudioPlayer audioPlayer; | 55 | late AudioPlayer audioPlayer; | 
| @@ -77,6 +58,8 @@ class TopicPictureBloc | @@ -77,6 +58,8 @@ class TopicPictureBloc | ||
| 77 | 58 | ||
| 78 | final Color? moduleColor; | 59 | final Color? moduleColor; | 
| 79 | 60 | ||
| 61 | + final String TAG = 'TopicPictureBloc'; | ||
| 62 | + | ||
| 80 | TopicPictureBloc( | 63 | TopicPictureBloc( | 
| 81 | this.context, this.pageController, this.courseLessonId, this.moduleColor) | 64 | this.context, this.pageController, this.courseLessonId, this.moduleColor) | 
| 82 | : super(TopicPictureInitial()) { | 65 | : super(TopicPictureInitial()) { | 
| @@ -90,24 +73,12 @@ class TopicPictureBloc | @@ -90,24 +73,12 @@ class TopicPictureBloc | ||
| 90 | on<XSVoiceStartEvent>(_voiceXsStart); | 73 | on<XSVoiceStartEvent>(_voiceXsStart); | 
| 91 | on<XSVoiceStopEvent>(_voiceXsStop); | 74 | on<XSVoiceStopEvent>(_voiceXsStop); | 
| 92 | on<VoicePlayEvent>(_questionVoicePlay); | 75 | on<VoicePlayEvent>(_questionVoicePlay); | 
| 76 | + on<OnXSVoiceStateChangeEvent>(_onVoiceXsStateChange); | ||
| 93 | on<InitBlocEvent>((event, emit) { | 77 | on<InitBlocEvent>((event, emit) { | 
| 94 | //音频播放器 | 78 | //音频播放器 | 
| 95 | audioPlayer = AudioPlayer(); | 79 | audioPlayer = AudioPlayer(); | 
| 96 | audioPlayer.onPlayerStateChanged.listen((event) async { | 80 | audioPlayer.onPlayerStateChanged.listen((event) async { | 
| 97 | - debugPrint('播放状态变化 _voicePlayState=$_voicePlayState event=$event'); | ||
| 98 | - if (event == PlayerState.completed) { | ||
| 99 | - debugPrint('播放完成'); | ||
| 100 | - _voicePlayState = VoicePlayState.completed; | ||
| 101 | - } | ||
| 102 | - if (event == PlayerState.stopped) { | ||
| 103 | - debugPrint('播放结束'); | ||
| 104 | - _voicePlayState = VoicePlayState.stop; | ||
| 105 | - } | ||
| 106 | - | ||
| 107 | - if (event == PlayerState.playing) { | ||
| 108 | - debugPrint('正在播放中'); | ||
| 109 | - _voicePlayState = VoicePlayState.playing; | ||
| 110 | - } | 81 | + Log.d('$TAG onPlayerStateChanged event=$event'); | 
| 111 | if (isClosed) { | 82 | if (isClosed) { | 
| 112 | return; | 83 | return; | 
| 113 | } | 84 | } | 
| @@ -130,16 +101,20 @@ class TopicPictureBloc | @@ -130,16 +101,20 @@ class TopicPictureBloc | ||
| 130 | if (kDebugMode) { | 101 | if (kDebugMode) { | 
| 131 | print('评测开始'); | 102 | print('评测开始'); | 
| 132 | } | 103 | } | 
| 104 | + _isRecording = true; | ||
| 105 | + add(OnXSVoiceStateChangeEvent()); | ||
| 133 | return; | 106 | return; | 
| 134 | } | 107 | } | 
| 135 | 108 | ||
| 136 | - if (call.method == 'voiceEnd') { | 109 | + if (call.method == 'voiceEnd' || call.method == 'voiceCancel') { | 
| 137 | await audioPlayer.setAudioContext(AudioContext()); | 110 | await audioPlayer.setAudioContext(AudioContext()); | 
| 138 | await audioPlayer.setBalance(0.0); | 111 | await audioPlayer.setBalance(0.0); | 
| 139 | //评测结束 | 112 | //评测结束 | 
| 140 | if (kDebugMode) { | 113 | if (kDebugMode) { | 
| 141 | - print('评测结束'); | 114 | + print(call.method == 'voiceEnd' ? '评测结束' : '评测取消'); | 
| 142 | } | 115 | } | 
| 116 | + _isRecording = false; | ||
| 117 | + add(OnXSVoiceStateChangeEvent()); | ||
| 143 | return; | 118 | return; | 
| 144 | } | 119 | } | 
| 145 | 120 | ||
| @@ -148,6 +123,8 @@ class TopicPictureBloc | @@ -148,6 +123,8 @@ class TopicPictureBloc | ||
| 148 | await audioPlayer.setAudioContext(AudioContext()); | 123 | await audioPlayer.setAudioContext(AudioContext()); | 
| 149 | await audioPlayer.setBalance(0.0); | 124 | await audioPlayer.setBalance(0.0); | 
| 150 | 125 | ||
| 126 | + _isRecording = false; | ||
| 127 | + add(OnXSVoiceStateChangeEvent()); | ||
| 151 | EasyLoading.showToast('评测失败'); | 128 | EasyLoading.showToast('评测失败'); | 
| 152 | return; | 129 | return; | 
| 153 | } | 130 | } | 
| @@ -157,10 +134,15 @@ class TopicPictureBloc | @@ -157,10 +134,15 @@ class TopicPictureBloc | ||
| 157 | }); | 134 | }); | 
| 158 | } | 135 | } | 
| 159 | 136 | ||
| 137 | + void _onVoiceXsStateChange(OnXSVoiceStateChangeEvent event, | ||
| 138 | + Emitter<TopicPictureState> emitter) async { | ||
| 139 | + emitter(XSVoiceTestState()); | ||
| 140 | + } | ||
| 141 | + | ||
| 160 | @override | 142 | @override | 
| 161 | Future<void> didChangeAppLifecycleState(AppLifecycleState state) async { | 143 | Future<void> didChangeAppLifecycleState(AppLifecycleState state) async { | 
| 162 | super.didChangeAppLifecycleState(state); | 144 | super.didChangeAppLifecycleState(state); | 
| 163 | - Log.d('TopicPictureBloc didChangeAppLifecycleState state=$state'); | 145 | + Log.d('$TAG didChangeAppLifecycleState state=$state'); | 
| 164 | if (state == AppLifecycleState.paused) { | 146 | if (state == AppLifecycleState.paused) { | 
| 165 | ///切到后台暂停音频播放、录音等 | 147 | ///切到后台暂停音频播放、录音等 | 
| 166 | if (audioPlayer.state == PlayerState.playing) { | 148 | if (audioPlayer.state == PlayerState.playing) { | 
| @@ -197,7 +179,7 @@ class TopicPictureBloc | @@ -197,7 +179,7 @@ class TopicPictureBloc | ||
| 197 | void _pageControllerChange(CurrentPageIndexChangeEvent event, | 179 | void _pageControllerChange(CurrentPageIndexChangeEvent event, | 
| 198 | Emitter<TopicPictureState> emitter) async { | 180 | Emitter<TopicPictureState> emitter) async { | 
| 199 | await pageResetIfNeed(); | 181 | await pageResetIfNeed(); | 
| 200 | - debugPrint('翻页 $_currentPage->${event.pageIndex}'); | 182 | + Log.d('$TAG _pageControllerChange $_currentPage->${event.pageIndex}'); | 
| 201 | if (_currentPage == _entity?.topics?.length) { | 183 | if (_currentPage == _entity?.topics?.length) { | 
| 202 | return; | 184 | return; | 
| 203 | } | 185 | } | 
| @@ -276,8 +258,6 @@ class TopicPictureBloc | @@ -276,8 +258,6 @@ class TopicPictureBloc | ||
| 276 | 'type': event.type, | 258 | 'type': event.type, | 
| 277 | 'userId': event.userId.toString() | 259 | 'userId': event.userId.toString() | 
| 278 | }); | 260 | }); | 
| 279 | - _isRecording = true; | ||
| 280 | - emitter(XSVoiceTestState()); | ||
| 281 | } | 261 | } | 
| 282 | } | 262 | } | 
| 283 | 263 | ||
| @@ -321,6 +301,10 @@ class TopicPictureBloc | @@ -321,6 +301,10 @@ class TopicPictureBloc | ||
| 321 | emitter(VoicePlayStateChange()); | 301 | emitter(VoicePlayStateChange()); | 
| 322 | } | 302 | } | 
| 323 | 303 | ||
| 304 | + bool isAudioPlaying() { | ||
| 305 | + return audioPlayer.state == PlayerState.playing; | ||
| 306 | + } | ||
| 307 | + | ||
| 324 | // 题目音频播放 | 308 | // 题目音频播放 | 
| 325 | void _questionVoicePlay( | 309 | void _questionVoicePlay( | 
| 326 | VoicePlayEvent event, Emitter<TopicPictureState> emitter) async { | 310 | VoicePlayEvent event, Emitter<TopicPictureState> emitter) async { | 
| @@ -335,7 +319,6 @@ class TopicPictureBloc | @@ -335,7 +319,6 @@ class TopicPictureBloc | ||
| 335 | Future<void> pageResetIfNeed() async { | 319 | Future<void> pageResetIfNeed() async { | 
| 336 | _optionSelectItem = -1; | 320 | _optionSelectItem = -1; | 
| 337 | _isRecording = false; | 321 | _isRecording = false; | 
| 338 | - _voicePlayState = VoicePlayState.stop; | ||
| 339 | 322 | ||
| 340 | await closePlayerResource(); | 323 | await closePlayerResource(); | 
| 341 | await _voiceXsCancel(); | 324 | await _voiceXsCancel(); | 
| @@ -347,7 +330,7 @@ class TopicPictureBloc | @@ -347,7 +330,7 @@ class TopicPictureBloc | ||
| 347 | } | 330 | } | 
| 348 | 331 | ||
| 349 | Future<void> closePlayerResource() async { | 332 | Future<void> closePlayerResource() async { | 
| 350 | - if (voicePlayState == VoicePlayState.playing) { | 333 | + if (isAudioPlaying()) { | 
| 351 | await audioPlayer.stop(); | 334 | await audioPlayer.stop(); | 
| 352 | } | 335 | } | 
| 353 | } | 336 | } | 
lib/pages/practice/bloc/topic_picture_event.dart
| @@ -30,6 +30,9 @@ class XSVoiceResultEvent extends TopicPictureEvent { | @@ -30,6 +30,9 @@ class XSVoiceResultEvent extends TopicPictureEvent { | ||
| 30 | XSVoiceResultEvent(this.message); | 30 | XSVoiceResultEvent(this.message); | 
| 31 | } | 31 | } | 
| 32 | 32 | ||
| 33 | +///先声评测状态 | ||
| 34 | +class OnXSVoiceStateChangeEvent extends TopicPictureEvent {} | ||
| 35 | + | ||
| 33 | ///音频播放状态变化 | 36 | ///音频播放状态变化 | 
| 34 | class VoicePlayStateChangeEvent extends TopicPictureEvent {} | 37 | class VoicePlayStateChangeEvent extends TopicPictureEvent {} | 
| 35 | 38 | 
lib/pages/practice/topic_picture_page.dart
| @@ -311,7 +311,7 @@ class _TopicPicturePage extends StatelessWidget { | @@ -311,7 +311,7 @@ class _TopicPicturePage extends StatelessWidget { | ||
| 311 | children: [ | 311 | children: [ | 
| 312 | SpeakerWidget( | 312 | SpeakerWidget( | 
| 313 | isPlaying: isCurrentPage && | 313 | isPlaying: isCurrentPage && | 
| 314 | - bloc.voicePlayState == VoicePlayState.playing, | 314 | + bloc.isAudioPlaying(), | 
| 315 | // 控制动画播放 | 315 | // 控制动画播放 | 
| 316 | width: 32.w, | 316 | width: 32.w, | 
| 317 | height: 32.w, | 317 | height: 32.w, | 
| @@ -392,7 +392,7 @@ class _TopicPicturePage extends StatelessWidget { | @@ -392,7 +392,7 @@ class _TopicPicturePage extends StatelessWidget { | ||
| 392 | children: [ | 392 | children: [ | 
| 393 | SpeakerWidget( | 393 | SpeakerWidget( | 
| 394 | isPlaying: isCurrentPage && | 394 | isPlaying: isCurrentPage && | 
| 395 | - bloc.voicePlayState == VoicePlayState.playing, | 395 | + bloc.isAudioPlaying(), | 
| 396 | width: 32.w, | 396 | width: 32.w, | 
| 397 | height: 32.w, | 397 | height: 32.w, | 
| 398 | onTap: () { | 398 | onTap: () { | 
| @@ -505,7 +505,7 @@ class _TopicPicturePage extends StatelessWidget { | @@ -505,7 +505,7 @@ class _TopicPicturePage extends StatelessWidget { | ||
| 505 | children: [ | 505 | children: [ | 
| 506 | SpeakerWidget( | 506 | SpeakerWidget( | 
| 507 | isPlaying: isCurrentPage && | 507 | isPlaying: isCurrentPage && | 
| 508 | - bloc.voicePlayState == VoicePlayState.playing, | 508 | + bloc.isAudioPlaying(), | 
| 509 | // 控制动画播放 | 509 | // 控制动画播放 | 
| 510 | isClickable: !bloc.isRecording, | 510 | isClickable: !bloc.isRecording, | 
| 511 | // 控制是否可点击 | 511 | // 控制是否可点击 | 
lib/pages/reading/bloc/reading_bloc.dart
| @@ -170,10 +170,11 @@ class ReadingPageBloc | @@ -170,10 +170,11 @@ class ReadingPageBloc | ||
| 170 | 170 | ||
| 171 | if (call.method == 'voiceFail') { | 171 | if (call.method == 'voiceFail') { | 
| 172 | //评测失败 | 172 | //评测失败 | 
| 173 | - _isRecording = false; | ||
| 174 | await audioPlayer.setAudioContext(AudioContext()); | 173 | await audioPlayer.setAudioContext(AudioContext()); | 
| 175 | await audioPlayer.setBalance(0.0); | 174 | await audioPlayer.setBalance(0.0); | 
| 176 | 175 | ||
| 176 | + _isRecording = false; | ||
| 177 | + add(OnXSVoiceStateChangeEvent()); | ||
| 177 | EasyLoading.showToast('评测失败'); | 178 | EasyLoading.showToast('评测失败'); | 
| 178 | return; | 179 | return; | 
| 179 | } | 180 | } | 
