Flutter BLoC/Cubit Timer App

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.

Cubit States

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];
}

Cubit Class

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.

Recent posts