How to dynamically change fields in blocs flutter

36 Views Asked by At

I am playing around with the Flutter Timer example in bloc (https://bloclibrary.dev/ja/tutorials/flutter-timer/) and I am just wondering how to dynamically change the initial value of the fields in bloc. Should be through event, can be just directly or what it is the correct way to define the duration parameter in TimerBloc Class

import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:fasting_app/models/ticker.dart';

part 'timer_event.dart';
part 'timer_state.dart';

class TimerBloc extends Bloc<TimerEvent, TimerState> {
  final Ticker _ticker;

  // this is what I want to change below in some widget outside
  static var _duration = 60;

  StreamSubscription<int>? _tickerSubscription;

  TimerBloc({required Ticker ticker})
      : _ticker = ticker,
        super(TimerInitial(_duration)) {
          //como cambiar este estado inicial dinamico
    on<TimerStarted>(_onStarted);
    on<TimerTicked>(_onTicked);
    on<TimerReset>(_onReset);
  }

  @override
  Future<void> close() {
    _tickerSubscription?.cancel();
    return super.close();
  }

  void _onStarted(TimerStarted event, Emitter<TimerState> emit) {
    _tickerSubscription?.cancel();

    emit(TimerRunInProgress(event.duration));
  //como cambiar los ticks dinamicamente
      _tickerSubscription = _ticker
        .tick(ticks: _duration)
        .listen((duration) => add(TimerTicked(duration)));
  }

  void _onTicked(TimerTicked event, Emitter<TimerState> emit) {
    //if event== state 60==60 then stop
    emit(event.duration != state.duration
        ? TimerRunInProgress(event.duration)

        /// triggers the TimerRunInProgress state
        : TimerRunComplete(_duration));
  }

  void _onReset(TimerReset event, Emitter<TimerState> emit) {
    /// Timer counting finished, so we must cancel the subscription
    _tickerSubscription?.cancel();
    emit(TimerInitial(_duration));
  }
}

I tried this

Padding(
                  padding: const EdgeInsets.all(20.0),
                  child: SizedBox(
                    width: 100,
                    height: 50,
                    child: ElevatedButton(
                      onPressed: () {  
//I have tried this but does not access to _duration field at bloc just                       
                        context.read<TimerBloc>().add(const TimerStarted(startTime));
                      },
                      child: const Text('START'),
                    ),
                  ),
                ),
1

There are 1 best solutions below

0
KTT9 On

Add new event:

class TimerDurationChanged extends TimerEvent 
  final int duration;
  const TimerDurationChanged(this.duration);

Handle this event in your bloc:

class TimerBloc extends Bloc<TimerEvent, TimerState> {
      final Ticker _ticker;
      int _duration = 60; // Make this non-static to modify per instance
    
      StreamSubscription<int>? _tickerSubscription;
    
      TimerBloc({required Ticker ticker})
          : _ticker = ticker,
            super(TimerInitial(60)) {
        on<TimerStarted>(_onStarted);
        on<TimerTicked>(_onTicked);
        on<TimerReset>(_onReset);
        on<TimerDurationChanged>(_onDurationChanged); //add this
      }
    
      void _onDurationChanged(TimerDurationChanged event, Emitter<TimerState> emit) {
        _duration = event.duration;
        emit(TimerInitial(_duration));
      }

then:

 ElevatedButton(
  onPressed: () {  
    context.read<TimerBloc>().add(TimerDurationChanged(120));
  },
  child: const Text('CHANGE DURATION'),
),
ElevatedButton(
  onPressed: () {  
    context.read<TimerBloc>().add(TimerStarted(context.read<TimerBloc>().state.duration));
  },
  child: const Text('START'),
),