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