Commit 2512b58cfb93b0db16705ff0f2cc99cb6e84b76e
1 parent
0ebc6186
feat:性能优化-练习页PageView根据是否是当前页来决定build以及SpeakerWidget组件isPlaying
Showing
1 changed file
with
161 additions
and
145 deletions
lib/pages/practice/topic_picture_page.dart
... | ... | @@ -93,28 +93,36 @@ class _TopicPicturePage extends StatelessWidget { |
93 | 93 | bloc.add(CurrentPageIndexChangeEvent(index)); |
94 | 94 | }, |
95 | 95 | itemBuilder: (BuildContext context, int index) { |
96 | + final bloc = | |
97 | + BlocProvider.of<TopicPictureBloc>(context); | |
96 | 98 | CourseProcessTopics? topics = |
97 | 99 | bloc.entity?.topics![index]; |
100 | + bool isCurrentPage = | |
101 | + index == bloc.currentPage - 1; | |
98 | 102 | if (topics?.type == |
99 | 103 | TopicType.audioImageSelect.value) { |
100 | 104 | //听音选图 |
101 | 105 | return _pageViewVoicePictureItemWidget( |
102 | - topics); | |
106 | + topics, isCurrentPage); | |
103 | 107 | } else if (topics?.type == |
104 | 108 | TopicType.audioCharSelect.value) { |
105 | 109 | //听音选字 |
106 | - return _pageViewVoiceWordItemWidget(topics); | |
110 | + return _pageViewVoiceWordItemWidget( | |
111 | + topics, isCurrentPage); | |
107 | 112 | } else if (topics?.type == |
108 | 113 | TopicType.questionCharSelect.value) { |
109 | 114 | //看题选字 |
110 | - return _pageViewWordItemWidget(topics); | |
115 | + return _pageViewWordItemWidget( | |
116 | + topics, isCurrentPage); | |
111 | 117 | } else if (topics?.type == |
112 | 118 | TopicType.questionImageSelect.value) { |
113 | 119 | //看题选图 |
114 | - return _pageViewItemWidget(topics); | |
120 | + return _pageViewItemWidget( | |
121 | + topics, isCurrentPage); | |
115 | 122 | } else { |
116 | 123 | //语音问答 |
117 | - return _voiceAnswerItem(topics); | |
124 | + return _voiceAnswerItem( | |
125 | + topics, isCurrentPage); | |
118 | 126 | } |
119 | 127 | }), |
120 | 128 | ) |
... | ... | @@ -130,33 +138,34 @@ class _TopicPicturePage extends StatelessWidget { |
130 | 138 | }); |
131 | 139 | |
132 | 140 | ///看题选图 |
133 | - Widget _pageViewItemWidget(CourseProcessTopics? topics) => | |
141 | + Widget _pageViewItemWidget(CourseProcessTopics? topics, bool isCurrentPage) => | |
134 | 142 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
143 | + buildWhen: (_, s) => isCurrentPage, | |
135 | 144 | builder: (context, state) { |
136 | - return SafeArea( | |
137 | - child: Column( | |
138 | - children: [ | |
139 | - Text(topics?.word ?? '', | |
140 | - softWrap: true, | |
141 | - style: TextStyle( | |
142 | - fontSize: 21.sp, color: const Color(0xFF333333))), | |
143 | - 26.verticalSpace, | |
144 | - SizedBox( | |
145 | - height: 143.h, | |
146 | - width: 143.w * (topics?.topicAnswerList?.length ?? 0), | |
147 | - child: ListView.builder( | |
148 | - scrollDirection: Axis.horizontal, | |
149 | - physics: const NeverScrollableScrollPhysics(), | |
150 | - itemCount: topics?.topicAnswerList?.length ?? 0, | |
151 | - itemBuilder: (context, index) { | |
152 | - return _decodeImageWidget( | |
153 | - index, topics?.topicAnswerList?[index]); | |
154 | - }), | |
145 | + return SafeArea( | |
146 | + child: Column( | |
147 | + children: [ | |
148 | + Text(topics?.word ?? '', | |
149 | + softWrap: true, | |
150 | + style: TextStyle( | |
151 | + fontSize: 21.sp, color: const Color(0xFF333333))), | |
152 | + 26.verticalSpace, | |
153 | + SizedBox( | |
154 | + height: 143.h, | |
155 | + width: 143.w * (topics?.topicAnswerList?.length ?? 0), | |
156 | + child: ListView.builder( | |
157 | + scrollDirection: Axis.horizontal, | |
158 | + physics: const NeverScrollableScrollPhysics(), | |
159 | + itemCount: topics?.topicAnswerList?.length ?? 0, | |
160 | + itemBuilder: (context, index) { | |
161 | + return _decodeImageWidget( | |
162 | + index, topics?.topicAnswerList?[index]); | |
163 | + }), | |
164 | + ), | |
165 | + ], | |
155 | 166 | ), |
156 | - ], | |
157 | - ), | |
158 | - ); | |
159 | - }); | |
167 | + ); | |
168 | + }); | |
160 | 169 | |
161 | 170 | Widget _decodeImageWidget( |
162 | 171 | int index, CourseProcessTopicsTopicAnswerList? answerLis) => |
... | ... | @@ -198,33 +207,35 @@ class _TopicPicturePage extends StatelessWidget { |
198 | 207 | }); |
199 | 208 | |
200 | 209 | ///看题选字 |
201 | - Widget _pageViewWordItemWidget(CourseProcessTopics? topics) => | |
210 | + Widget _pageViewWordItemWidget( | |
211 | + CourseProcessTopics? topics, bool isCurrentPage) => | |
202 | 212 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
213 | + buildWhen: (_, s) => isCurrentPage, | |
203 | 214 | builder: (context, state) { |
204 | - return SafeArea( | |
205 | - child: Column( | |
206 | - children: [ | |
207 | - Text(topics?.word ?? '', | |
208 | - softWrap: true, | |
209 | - style: TextStyle( | |
210 | - fontSize: 21.sp, color: const Color(0xFF333333))), | |
211 | - 26.verticalSpace, | |
212 | - SizedBox( | |
213 | - height: 143.h, | |
214 | - width: 143.w * (topics?.topicAnswerList?.length ?? 0), | |
215 | - child: ListView.builder( | |
216 | - scrollDirection: Axis.horizontal, | |
217 | - itemCount: topics?.topicAnswerList?.length ?? 0, | |
218 | - physics: const NeverScrollableScrollPhysics(), | |
219 | - itemBuilder: (context, index) { | |
220 | - return _decodeWordWidget( | |
221 | - index, topics?.topicAnswerList?[index]); | |
222 | - }), | |
215 | + return SafeArea( | |
216 | + child: Column( | |
217 | + children: [ | |
218 | + Text(topics?.word ?? '', | |
219 | + softWrap: true, | |
220 | + style: TextStyle( | |
221 | + fontSize: 21.sp, color: const Color(0xFF333333))), | |
222 | + 26.verticalSpace, | |
223 | + SizedBox( | |
224 | + height: 143.h, | |
225 | + width: 143.w * (topics?.topicAnswerList?.length ?? 0), | |
226 | + child: ListView.builder( | |
227 | + scrollDirection: Axis.horizontal, | |
228 | + itemCount: topics?.topicAnswerList?.length ?? 0, | |
229 | + physics: const NeverScrollableScrollPhysics(), | |
230 | + itemBuilder: (context, index) { | |
231 | + return _decodeWordWidget( | |
232 | + index, topics?.topicAnswerList?[index]); | |
233 | + }), | |
234 | + ), | |
235 | + ], | |
223 | 236 | ), |
224 | - ], | |
225 | - ), | |
226 | - ); | |
227 | - }); | |
237 | + ); | |
238 | + }); | |
228 | 239 | |
229 | 240 | Widget _decodeWordWidget( |
230 | 241 | int index, CourseProcessTopicsTopicAnswerList? answerLis) => |
... | ... | @@ -285,9 +296,12 @@ class _TopicPicturePage extends StatelessWidget { |
285 | 296 | }); |
286 | 297 | |
287 | 298 | ///听音选图 |
288 | - Widget _pageViewVoicePictureItemWidget(CourseProcessTopics? topics) => | |
299 | + Widget _pageViewVoicePictureItemWidget( | |
300 | + CourseProcessTopics? topics, bool isCurrentPage) => | |
289 | 301 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
290 | - builder: (context, state) { | |
302 | + buildWhen: (previous, current) { | |
303 | + return isCurrentPage; | |
304 | + }, builder: (context, state) { | |
291 | 305 | final bloc = BlocProvider.of<TopicPictureBloc>(context); |
292 | 306 | return SafeArea( |
293 | 307 | child: Column( |
... | ... | @@ -296,10 +310,9 @@ class _TopicPicturePage extends StatelessWidget { |
296 | 310 | mainAxisAlignment: MainAxisAlignment.center, |
297 | 311 | children: [ |
298 | 312 | SpeakerWidget( |
299 | - isPlaying: bloc.voicePlayState == VoicePlayState.playing, | |
313 | + isPlaying: isCurrentPage && | |
314 | + bloc.voicePlayState == VoicePlayState.playing, | |
300 | 315 | // 控制动画播放 |
301 | - isClickable: true, | |
302 | - // 控制是否可点击 | |
303 | 316 | width: 32.w, |
304 | 317 | height: 32.w, |
305 | 318 | onTap: () { |
... | ... | @@ -368,41 +381,41 @@ class _TopicPicturePage extends StatelessWidget { |
368 | 381 | }); |
369 | 382 | |
370 | 383 | ///听音选字 |
371 | - Widget _pageViewVoiceWordItemWidget(CourseProcessTopics? topics) => | |
384 | + Widget _pageViewVoiceWordItemWidget( | |
385 | + CourseProcessTopics? topics, bool isCurrentPage) => | |
372 | 386 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
387 | + buildWhen: (_, s) => isCurrentPage, | |
373 | 388 | builder: (context, state) { |
374 | - final bloc = BlocProvider.of<TopicPictureBloc>(context); | |
375 | - return SafeArea( | |
376 | - child: Column( | |
377 | - children: [ | |
378 | - SpeakerWidget( | |
379 | - isPlaying: bloc.voicePlayState == VoicePlayState.playing, | |
380 | - // 控制动画播放 | |
381 | - isClickable: true, | |
382 | - // 控制是否可点击 | |
383 | - width: 32.w, | |
384 | - height: 32.w, | |
385 | - onTap: () { | |
386 | - bloc.add(VoicePlayEvent()); | |
387 | - }, | |
388 | - ), | |
389 | - 26.verticalSpace, | |
390 | - SizedBox( | |
391 | - width: 163.w * (topics?.topicAnswerList?.length ?? 0), | |
392 | - height: 143.h, | |
393 | - child: ListView.builder( | |
394 | - scrollDirection: Axis.horizontal, | |
395 | - itemCount: topics?.topicAnswerList?.length, | |
396 | - physics: const NeverScrollableScrollPhysics(), | |
397 | - itemBuilder: (BuildContext context, int index) { | |
398 | - return _decodeVoiceWordImageWidget( | |
399 | - index, topics!.topicAnswerList![index]); | |
400 | - }), | |
389 | + final bloc = BlocProvider.of<TopicPictureBloc>(context); | |
390 | + return SafeArea( | |
391 | + child: Column( | |
392 | + children: [ | |
393 | + SpeakerWidget( | |
394 | + isPlaying: isCurrentPage && | |
395 | + bloc.voicePlayState == VoicePlayState.playing, | |
396 | + width: 32.w, | |
397 | + height: 32.w, | |
398 | + onTap: () { | |
399 | + bloc.add(VoicePlayEvent()); | |
400 | + }, | |
401 | + ), | |
402 | + 26.verticalSpace, | |
403 | + SizedBox( | |
404 | + width: 163.w * (topics?.topicAnswerList?.length ?? 0), | |
405 | + height: 143.h, | |
406 | + child: ListView.builder( | |
407 | + scrollDirection: Axis.horizontal, | |
408 | + itemCount: topics?.topicAnswerList?.length, | |
409 | + physics: const NeverScrollableScrollPhysics(), | |
410 | + itemBuilder: (BuildContext context, int index) { | |
411 | + return _decodeVoiceWordImageWidget( | |
412 | + index, topics!.topicAnswerList![index]); | |
413 | + }), | |
414 | + ), | |
415 | + ], | |
401 | 416 | ), |
402 | - ], | |
403 | - ), | |
404 | - ); | |
405 | - }); | |
417 | + ); | |
418 | + }); | |
406 | 419 | |
407 | 420 | Widget _decodeVoiceWordImageWidget( |
408 | 421 | int index, CourseProcessTopicsTopicAnswerList answerList) => |
... | ... | @@ -465,71 +478,74 @@ class _TopicPicturePage extends StatelessWidget { |
465 | 478 | }); |
466 | 479 | |
467 | 480 | ///语音问答 |
468 | - Widget _voiceAnswerItem(CourseProcessTopics? topics) => | |
481 | + Widget _voiceAnswerItem(CourseProcessTopics? topics, bool isCurrentPage) => | |
469 | 482 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
483 | + buildWhen: (_, s) => isCurrentPage, | |
470 | 484 | builder: (context, state) { |
471 | - final bloc = BlocProvider.of<TopicPictureBloc>(context); | |
472 | - return Row( | |
473 | - mainAxisAlignment: MainAxisAlignment.center, | |
474 | - children: [ | |
475 | - ClipRRect( | |
476 | - borderRadius: BorderRadius.circular(20), | |
477 | - child: Container( | |
478 | - color: Colors.white, | |
479 | - child: OwImageWidget( | |
480 | - name: topics?.picUrl ?? '', | |
481 | - height: 186.h, | |
482 | - width: 186.w, | |
483 | - ), | |
484 | - ), | |
485 | - ), | |
486 | - 120.horizontalSpace, | |
487 | - Column( | |
485 | + final bloc = BlocProvider.of<TopicPictureBloc>(context); | |
486 | + return Row( | |
488 | 487 | mainAxisAlignment: MainAxisAlignment.center, |
489 | 488 | children: [ |
490 | - Row( | |
489 | + ClipRRect( | |
490 | + borderRadius: BorderRadius.circular(20), | |
491 | + child: Container( | |
492 | + color: Colors.white, | |
493 | + child: OwImageWidget( | |
494 | + name: topics?.picUrl ?? '', | |
495 | + height: 186.h, | |
496 | + width: 186.w, | |
497 | + ), | |
498 | + ), | |
499 | + ), | |
500 | + 120.horizontalSpace, | |
501 | + Column( | |
502 | + mainAxisAlignment: MainAxisAlignment.center, | |
491 | 503 | children: [ |
492 | - SpeakerWidget( | |
493 | - isPlaying: bloc.voicePlayState == VoicePlayState.playing, | |
494 | - // 控制动画播放 | |
495 | - isClickable: !bloc.isRecording, | |
496 | - // 控制是否可点击 | |
497 | - width: 45.w, | |
498 | - height: 45.w, | |
504 | + Row( | |
505 | + children: [ | |
506 | + SpeakerWidget( | |
507 | + isPlaying: isCurrentPage && | |
508 | + bloc.voicePlayState == VoicePlayState.playing, | |
509 | + // 控制动画播放 | |
510 | + isClickable: !bloc.isRecording, | |
511 | + // 控制是否可点击 | |
512 | + width: 45.w, | |
513 | + height: 45.w, | |
514 | + onTap: () { | |
515 | + bloc.add(VoicePlayEvent()); | |
516 | + }, | |
517 | + ), | |
518 | + 10.horizontalSpace, | |
519 | + Text(topics?.word ?? '') | |
520 | + ], | |
521 | + ), | |
522 | + 70.verticalSpace, | |
523 | + RecorderWidget( | |
524 | + isPlaying: bloc.isRecording, | |
525 | + isClickable: | |
526 | + bloc.voicePlayState != VoicePlayState.playing, | |
527 | + width: 72.w, | |
528 | + height: 72.w, | |
499 | 529 | onTap: () { |
500 | - bloc.add(VoicePlayEvent()); | |
530 | + if (bloc.isRecording) { | |
531 | + bloc.add(XSVoiceStopEvent()); | |
532 | + return; | |
533 | + } | |
534 | + if (topics?.type == TopicType.voiceQuestion.value || | |
535 | + topics?.type == TopicType.voiceWord.value) { | |
536 | + bloc.add(XSVoiceStartEvent(topics?.keyWord ?? '', '0', | |
537 | + UserUtil.getUser()!.id.toString())); | |
538 | + } else { | |
539 | + bloc.add(XSVoiceStartEvent(topics?.word ?? '', '0', | |
540 | + UserUtil.getUser()!.id.toString())); | |
541 | + } | |
501 | 542 | }, |
502 | 543 | ), |
503 | - 10.horizontalSpace, | |
504 | - Text(topics?.word ?? '') | |
505 | 544 | ], |
506 | - ), | |
507 | - 70.verticalSpace, | |
508 | - RecorderWidget( | |
509 | - isPlaying: bloc.isRecording, | |
510 | - isClickable: bloc.voicePlayState != VoicePlayState.playing, | |
511 | - width: 72.w, | |
512 | - height: 72.w, | |
513 | - onTap: () { | |
514 | - if (bloc.isRecording) { | |
515 | - bloc.add(XSVoiceStopEvent()); | |
516 | - return; | |
517 | - } | |
518 | - if (topics?.type == TopicType.voiceQuestion.value || | |
519 | - topics?.type == TopicType.voiceWord.value) { | |
520 | - bloc.add(XSVoiceStartEvent(topics?.keyWord ?? '', '0', | |
521 | - UserUtil.getUser()!.id.toString())); | |
522 | - } else { | |
523 | - bloc.add(XSVoiceStartEvent(topics?.word ?? '', '0', | |
524 | - UserUtil.getUser()!.id.toString())); | |
525 | - } | |
526 | - }, | |
527 | - ), | |
545 | + ) | |
528 | 546 | ], |
529 | - ) | |
530 | - ], | |
531 | - ); | |
532 | - }); | |
547 | + ); | |
548 | + }); | |
533 | 549 | |
534 | 550 | Color getResultColor(bool correct) { |
535 | 551 | if (correct) { | ... | ... |