Flutter BLoC/Cubit Timer App
First we will do this app using Cubit. Then we will see how to convert this Cubit to BLoC app. Previoulsy we used Getx for Timer app.
In this timer app, we will start the timer on a button click, and then we will count to certain time and then we will stop the timer.
That means we will have to have two states. One for triggering the initial state and we will call it InitialState and other one is the button click state and we will call it WorkoutInProgress . WorkoutInProgress will start the timer.
Each time is WorkoutInProgress called elapsed is increased by one. The initial value of elapsed is zero.
Once it is triggered we will start counting the time.
Let's create a class name timer_states.dart
import 'package:equatable/equatable.dart';
abstract class WorkoutState extends Equatable{
final int? elapsed;
const WorkoutState(this.elapsed);
}
class WorkoutInitial extends WorkoutState{
const WorkoutInitial():super(0);
@override
// TODO: implement props
List<Object?> get props => [];
}
class WorkoutInProgress extends WorkoutState{
const WorkoutInProgress(int? elapsed):
super(elapsed);
@override
// TODO: implement props
List<Object?> get props => [ elapsed];
}
Since we are using Cubit, we don't need any events. We need to create methods() and those methods() would be called from the UI using BlocProvider.
And the methods would trigger states using emit() function.
Let's create a cubit class name timer_cubits.dart
class WorkoutCubit extends Cubit<WorkoutState>{
WorkoutCubit():super(const WorkoutInitial());
Timer? _timer;
onTick(Timer timer){
if(state is WorkoutInProgress){
WorkoutInProgress wip = state as WorkoutInProgress;
if(wip.elapsed!< 110){
emit(WorkoutInProgress( wip.elapsed!+1));
}else{
_timer!.cancel();
Wakelock.disable();
emit(const WorkoutInitial());
}
}
}
startWorkout( [int? index]){
Wakelock.enable();
if(index != null){
emit(const WorkoutInProgress( 0));
}else{
emit(const WorkoutInProgress( 0));
}
_timer = Timer.periodic(const Duration(seconds: 1), onTick);
}
}
sartWorkout, initializes the _timer object with Timer.periodic(), it takes a duration object and a callback function.
The onTick callback function emits states every one second later.
Our main.dart
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Home()
);
}
}
class Home extends StatelessWidget {
const Home({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => WorkoutCubit(),
child: Scaffold(
appBar: AppBar(
title: const Text('The BLoC App'),
),
body: BlocBuilder<WorkoutCubit, WorkoutState>(
builder: (context, state) {
if (state is WorkoutInitial) {
return Center(
child: ElevatedButton(
onPressed: ()=>BlocProvider.of<WorkoutCubit>(context).startWorkout(0),
child: Text("Start")),
);
}
if(state is WorkoutInProgress){
print("${state.elapsed}");
return Center(child: Text("${state.elapsed!}"),);
}
return Container();
},
),
),
);
}
}
Here we started the timer and continued to the end. If you wanna learn how to stop there timer click here.
2024-08-04 16:00:32
you didn't close your timer onClose
Ok. Sorry it happens sometimes. But easy to solve though