Sparround

EventTransformer və müşahidə (BlocObserver)

Rəsmi sənəd Bloc-un Cubit üzərindəki ikinci üstünlüyünü advanced event transformations adlandırır: buffer, debounce, throttle kimi reaktiv operatorlardan istifadə etmək imkanı.

Mexanizm: on<Event> çağırışına transformer parametri verilir. EventTransformer<T> gələn event axınının bloc tərəfindən necə işlənəcəyini dəyişir.

Hazır transformer-lər package:bloc_concurrency paketindədir:

  • `concurrent` — event-ləri paralel işləyir.
  • `sequential` — event-ləri bir-bir, ardıcıl işləyir.
  • `droppable` — bir event işlənərkən əlavə olunan event-ləri atır.
  • `restartable` — yalnız son event-i işləyir, əvvəlkiləri ləğv edir.
SsenariTransformerSəbəb
Axtarış sahəsinə yazmaq`restartable` (+ debounce)Yalnız son sorğunun nəticəsi lazımdır; köhnə sorğular ləğv olunur
"Ödə" düyməsinə iki dəfə basmaq`droppable`İkinci sorğu atılır — ikiqat əməliyyatın qarşısı alınır
Səhifələmə: "daha çox yüklə"`droppable`Scroll zamanı təkrar sorğuların qarşısını alır
Analytics event-lərinin göndərilməsi`sequential`Ardıcıllıq vacibdir, heç bir event itməməlidir
Bir-birindən müstəqil yükləmələr`concurrent`Paralel icra ən sürətlidir
dart
import 'package:bloc_concurrency/bloc_concurrency.dart';
import 'package:stream_transform/stream_transform.dart';

EventTransformer<E> debounceRestartable<E>(Duration duration) {
  return (events, mapper) =>
      restartable<E>().call(events.debounce(duration), mapper);
}

class SearchBloc extends Bloc<SearchEvent, SearchState> {
  SearchBloc(this._repository) : super(const SearchState()) {
    on<SearchQueryChanged>(
      _onQueryChanged,
      // Sürətli yazılışda yalnız son sorğu işlənir, əvvəlkilər ləğv olunur.
      transformer: debounceRestartable(const Duration(milliseconds: 300)),
    );
  }

  final SearchRepository _repository;

  Future<void> _onQueryChanged(
    SearchQueryChanged event,
    Emitter<SearchState> emit,
  ) async {
    if (event.query.isEmpty) {
      emit(const SearchState());
      return;
    }
    emit(state.copyWith(status: SearchStatus.loading));
    final results = await _repository.search(event.query);
    emit(state.copyWith(status: SearchStatus.success, results: results));
  }
}

Axtarış: debounce + restartable.

Müşahidə: BlocObserver. Bütün bloc və cubit-lərin həyat dövrünü bir yerdən izləmək üçün BlocObserver override olunur:

  • onCreate — bloc yaradıldı
  • onEvent — bloc-a event əlavə olundu
  • onChange — state dəyişdi (cubit-lərdə də)
  • onTransitionstate → event → state keçidi; sənədə görə Transition cari state, event və növbəti state-dən ibarətdir və onTransition onChange-dən əvvəl çağırılır
  • onError — xəta
  • onClose — bloc bağlandı

Qeydiyyat: Bloc.observer = MyObserver(); və ya bir neçəsini birləşdirmək üçün Bloc.observer = MultiBlocObserver(observers: [...]);

Bu, müsahibədə BLoC-un traceability üstünlüyünün konkret sübutudur: log-da hansı event-in hansı state keçidini doğurduğu görünür — Cubit-də event obyekti olmadığı üçün bu məlumat yoxdur.

dart
class AppBlocObserver extends BlocObserver {
  const AppBlocObserver();

  @override
  void onEvent(Bloc bloc, Object? event) {
    super.onEvent(bloc, event);
    // Audit tələb olunan axınlarda event jurnalı buradan yazılır.
    log('${bloc.runtimeType} ← $event');
  }

  @override
  void onTransition(Bloc bloc, Transition transition) {
    super.onTransition(bloc, transition);
    // Transition: cari state + event + növbəti state.
    log('${bloc.runtimeType} ${transition.currentState.runtimeType} '
        '--${transition.event.runtimeType}--> ${transition.nextState.runtimeType}');
  }

  @override
  void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
    // Crash reporting servisinə göndərmək üçün mərkəzi nöqtə.
    reportError(error, stackTrace, context: bloc.runtimeType.toString());
    super.onError(bloc, error, stackTrace);
  }
}

void main() {
  Bloc.observer = const AppBlocObserver();
  runApp(const MyApp());
}

Observer: log və crash reporting bir yerdə.

Transformer seçimini təxminə buraxmayın: kritik axınlarda (ödəniş, sifariş yaratma, səhifələmə) transformer parametrini açıq şəkildə yazın və bunu code review checklist-inə salın. "İki dəfə basıldı → iki sifariş" tipli bug-lar məhz sükutla qəbul edilmiş davranışdan doğur.

📚 Mənbələr və sənədlər