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,28 +93,36 @@ class _TopicPicturePage extends StatelessWidget { | ||
93 | bloc.add(CurrentPageIndexChangeEvent(index)); | 93 | bloc.add(CurrentPageIndexChangeEvent(index)); |
94 | }, | 94 | }, |
95 | itemBuilder: (BuildContext context, int index) { | 95 | itemBuilder: (BuildContext context, int index) { |
96 | + final bloc = | ||
97 | + BlocProvider.of<TopicPictureBloc>(context); | ||
96 | CourseProcessTopics? topics = | 98 | CourseProcessTopics? topics = |
97 | bloc.entity?.topics![index]; | 99 | bloc.entity?.topics![index]; |
100 | + bool isCurrentPage = | ||
101 | + index == bloc.currentPage - 1; | ||
98 | if (topics?.type == | 102 | if (topics?.type == |
99 | TopicType.audioImageSelect.value) { | 103 | TopicType.audioImageSelect.value) { |
100 | //听音选图 | 104 | //听音选图 |
101 | return _pageViewVoicePictureItemWidget( | 105 | return _pageViewVoicePictureItemWidget( |
102 | - topics); | 106 | + topics, isCurrentPage); |
103 | } else if (topics?.type == | 107 | } else if (topics?.type == |
104 | TopicType.audioCharSelect.value) { | 108 | TopicType.audioCharSelect.value) { |
105 | //听音选字 | 109 | //听音选字 |
106 | - return _pageViewVoiceWordItemWidget(topics); | 110 | + return _pageViewVoiceWordItemWidget( |
111 | + topics, isCurrentPage); | ||
107 | } else if (topics?.type == | 112 | } else if (topics?.type == |
108 | TopicType.questionCharSelect.value) { | 113 | TopicType.questionCharSelect.value) { |
109 | //看题选字 | 114 | //看题选字 |
110 | - return _pageViewWordItemWidget(topics); | 115 | + return _pageViewWordItemWidget( |
116 | + topics, isCurrentPage); | ||
111 | } else if (topics?.type == | 117 | } else if (topics?.type == |
112 | TopicType.questionImageSelect.value) { | 118 | TopicType.questionImageSelect.value) { |
113 | //看题选图 | 119 | //看题选图 |
114 | - return _pageViewItemWidget(topics); | 120 | + return _pageViewItemWidget( |
121 | + topics, isCurrentPage); | ||
115 | } else { | 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,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 | BlocBuilder<TopicPictureBloc, TopicPictureState>( | 142 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
143 | + buildWhen: (_, s) => isCurrentPage, | ||
135 | builder: (context, state) { | 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 | Widget _decodeImageWidget( | 170 | Widget _decodeImageWidget( |
162 | int index, CourseProcessTopicsTopicAnswerList? answerLis) => | 171 | int index, CourseProcessTopicsTopicAnswerList? answerLis) => |
@@ -198,33 +207,35 @@ class _TopicPicturePage extends StatelessWidget { | @@ -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 | BlocBuilder<TopicPictureBloc, TopicPictureState>( | 212 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
213 | + buildWhen: (_, s) => isCurrentPage, | ||
203 | builder: (context, state) { | 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 | Widget _decodeWordWidget( | 240 | Widget _decodeWordWidget( |
230 | int index, CourseProcessTopicsTopicAnswerList? answerLis) => | 241 | int index, CourseProcessTopicsTopicAnswerList? answerLis) => |
@@ -285,9 +296,12 @@ class _TopicPicturePage extends StatelessWidget { | @@ -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 | BlocBuilder<TopicPictureBloc, TopicPictureState>( | 301 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
290 | - builder: (context, state) { | 302 | + buildWhen: (previous, current) { |
303 | + return isCurrentPage; | ||
304 | + }, builder: (context, state) { | ||
291 | final bloc = BlocProvider.of<TopicPictureBloc>(context); | 305 | final bloc = BlocProvider.of<TopicPictureBloc>(context); |
292 | return SafeArea( | 306 | return SafeArea( |
293 | child: Column( | 307 | child: Column( |
@@ -296,10 +310,9 @@ class _TopicPicturePage extends StatelessWidget { | @@ -296,10 +310,9 @@ class _TopicPicturePage extends StatelessWidget { | ||
296 | mainAxisAlignment: MainAxisAlignment.center, | 310 | mainAxisAlignment: MainAxisAlignment.center, |
297 | children: [ | 311 | children: [ |
298 | SpeakerWidget( | 312 | SpeakerWidget( |
299 | - isPlaying: bloc.voicePlayState == VoicePlayState.playing, | 313 | + isPlaying: isCurrentPage && |
314 | + bloc.voicePlayState == VoicePlayState.playing, | ||
300 | // 控制动画播放 | 315 | // 控制动画播放 |
301 | - isClickable: true, | ||
302 | - // 控制是否可点击 | ||
303 | width: 32.w, | 316 | width: 32.w, |
304 | height: 32.w, | 317 | height: 32.w, |
305 | onTap: () { | 318 | onTap: () { |
@@ -368,41 +381,41 @@ class _TopicPicturePage extends StatelessWidget { | @@ -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 | BlocBuilder<TopicPictureBloc, TopicPictureState>( | 386 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
387 | + buildWhen: (_, s) => isCurrentPage, | ||
373 | builder: (context, state) { | 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 | Widget _decodeVoiceWordImageWidget( | 420 | Widget _decodeVoiceWordImageWidget( |
408 | int index, CourseProcessTopicsTopicAnswerList answerList) => | 421 | int index, CourseProcessTopicsTopicAnswerList answerList) => |
@@ -465,71 +478,74 @@ class _TopicPicturePage extends StatelessWidget { | @@ -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 | BlocBuilder<TopicPictureBloc, TopicPictureState>( | 482 | BlocBuilder<TopicPictureBloc, TopicPictureState>( |
483 | + buildWhen: (_, s) => isCurrentPage, | ||
470 | builder: (context, state) { | 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 | mainAxisAlignment: MainAxisAlignment.center, | 487 | mainAxisAlignment: MainAxisAlignment.center, |
489 | children: [ | 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 | children: [ | 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 | onTap: () { | 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 | Color getResultColor(bool correct) { | 550 | Color getResultColor(bool correct) { |
535 | if (correct) { | 551 | if (correct) { |