我陷入了一个奇怪的境地。交叉检查了所有参考资料。问题是我的计时器没有更新 modelBottomSheet。 这是我的锻炼追踪器
class WorkOutTracker extends StatefulWidget {
const WorkOutTracker({Key? key}) : super(key: key);
@override
State<WorkOutTracker> createState() => _WorkOutTrackerState();
}
class _WorkOutTrackerState extends State<WorkOutTracker> {
final WorkoutBloc workoutBloc = WorkoutBloc();
String elapsedTime = "0s";
late Timer timer;
void updateElapsedTime(Timer timer) {
workoutBloc.add(StartWorkout(timer: timer));
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: BlocConsumer<WorkoutBloc, WorkoutState>(
bloc: workoutBloc,
listenWhen: (previous, current) => current is WorkoutActionState,
buildWhen: (previous, current) => current is! WorkoutActionState,
listener: (context, state) {
// TODO: implement listener
print("sdsd");
},
builder: (context, state) {
return Scaffold(
body: Column(
children: [
Expanded(
child: SingleChildScrollView(
child: Column(
children: [
_buildStartWorkoutButton(),
],
),
),
),
if (state is Workingout) _buildResumeCancelButtons(),
],
),
);
},
),
);
}
Widget _buildStartWorkoutButton() {
return Column(
children: [
const Align(
alignment: Alignment.centerLeft,
child: Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'Start workout',
style: TextStyle(
color: Colors.black,
fontSize: 25,
fontWeight: FontWeight.bold,
),
),
),
),
Center(
child: ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(6.0)),
),
),
),
child: const Text(
'Start with new routine',
style: TextStyle(color: Colors.black),
),
onPressed: () => _onStartWorkoutButtonPressed(context),
),
),
],
);
}
Widget _buildResumeCancelButtons() {
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.blueAccent),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(6.0)),
),
),
),
child: const Text(
'Resume workout',
style: TextStyle(color: Colors.black),
),
onPressed: () => _onResumeWorkoutButtonPressed(context),
),
ElevatedButton(
style: ButtonStyle(
backgroundColor: MaterialStateProperty.all(Colors.blue),
shape: MaterialStateProperty.all<RoundedRectangleBorder>(
const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(6.0)),
),
),
),
child: const Text(
'Cancel workout',
style: TextStyle(color: Colors.black),
),
onPressed: () => _onCancelWorkoutButtonPressed(),
),
],
),
);
}
void _onStartWorkoutButtonPressed(BuildContext context) {
timer = Timer.periodic(
const Duration(seconds: 1),
(Timer t) {
updateElapsedTime(t);
},
);
showModalBottomSheet<dynamic>(
isScrollControlled: true,
context: context,
builder: (BuildContext context) {
return ExcerciseTracker();
},
);
}
void _onResumeWorkoutButtonPressed(BuildContext context) {
showModalBottomSheet<dynamic>(
isScrollControlled: true,
context: context,
builder: (BuildContext context) {
return ExcerciseTracker();
},
);
}
void _onCancelWorkoutButtonPressed() {
timer.cancel();
workoutBloc.add(EndWorkout());
}
}
请关注 _onStartWorkoutButtonPressed,这里我正在启动一个计时器并显示一个 modalBottomSheet。
下一个文件是 WorkoutBloc
class WorkoutBloc extends Bloc<WorkoutEvent, WorkoutState> {
WorkoutBloc() : super(WorkoutInitial()) {
on<StartWorkout>(startWorkout);
on<EndWorkout>(endWorkout);
on<ResumeWorkout>(resumeWorkout);
}
FutureOr<void> startWorkout(
StartWorkout event, Emitter<WorkoutState> emit) async {
//starting workout
try {
print(event.timer.tick);
return emit(Workingout(second: event.timer.tick));
} catch (e) {
emit(Error());
}
}
FutureOr<void> endWorkout(
EndWorkout event, Emitter<WorkoutState> emit) async {
try {
return emit(EndWorkingout());
} catch (e) {
emit(Error());
}
}
FutureOr<void> resumeWorkout(
ResumeWorkout event, Emitter<WorkoutState> emit) {}
}
此文件在每次更改时都会产生“锻炼”状态。我已经通过 print 语句验证了它,并且工作正常。
还有最后一个文件
class ExcerciseTracker extends StatefulWidget {
const ExcerciseTracker({super.key});
@override
State<ExcerciseTracker> createState() => _ExcerciseTrackerState();
}
class _ExcerciseTrackerState extends State<ExcerciseTracker> {
final WorkoutBloc workoutBloc = WorkoutBloc();
@override
Widget build(BuildContext context) {
return SizedBox(
height: MediaQuery.of(context).size.height * 0.85,
child: BlocConsumer<WorkoutBloc, WorkoutState>(
bloc: workoutBloc,
listenWhen: (previous, current) => current is WorkoutActionState,
buildWhen: (previous, current) => current is! WorkoutActionState,
listener: (context, state) {
// TODO: implement listener
print("sdsd");
},
builder: (context, state) {
print("BlocConsumer rebuilt with state: $state");
return Column(
children: [
Padding(
padding: const EdgeInsets.all(10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// Taken from here https://unicode.org/Public/emoji/1.0/emoji-data.txt
const Text(
'\u{1F525} 234 ',
style: TextStyle(
fontSize: 18.0, fontWeight: FontWeight.bold),
),
Text(
_getFormattedElapsedTime(state).toString(),
style: const TextStyle(
fontSize: 18.0, fontWeight: FontWeight.bold),
),
IconButton(
icon: const Icon(
Icons.close,
color: Colors.black,
size: 30.0,
semanticLabel:
'Text to announce in accessibility modes',
),
onPressed: () {
Navigator.pop(context);
},
),
],
),
),
],
);
},
),
);
}
String _getFormattedElapsedTime(WorkoutState state) {
// Calculate elapsed time using the timer
print(state.toString());
int seconds = state is Workingout ? state.second : 10;
int minutes = seconds ~/ 60;
seconds %= 60;
return '$minutes:${seconds.toString().padLeft(2, '0')}';
}
}
这个文件就是问题所在,
print(state.toString());
只打印Instance of 'WorkoutInitial'
并且没有获得锻炼状态。
有人可以向我解释一下为什么会发生这种情况吗?
谢谢。
我遇到了类似的问题,如果我没记错的话,modalBottomSheet 或对话框正在创建自己的上下文,您无法在那里访问您的块。您必须将块传递给 modalBottomSheet(例如 ExcerciseTracker())作为参数,以确保您使用块的相同实例,否则您将使用所有初始值创建块的新实例。
也许它可以帮助你。