Ответ
В контексте архитектуры Flutter-приложений (например, BLoC, Provider, Riverpod) Handler (или обработчик) — это функция или метод, который отвечает за реакцию на событие или изменение состояния. Он содержит бизнес-логику: обрабатывает пользовательский ввод, выполняет запросы к API, трансформирует данные и emits новое состояние.
Пример Handler'а в паттерне BLoC (с использованием flutter_bloc):
// Событие
class LoginButtonPressed extends AuthEvent {
final String email;
final String password;
LoginButtonPressed({required this.email, required this.password});
}
// BLoC с Handler'ом (метод mapEventToState или on<Event>)
class AuthBloc extends Bloc<AuthEvent, AuthState> {
final AuthRepository authRepo;
AuthBloc(this.authRepo) : super(AuthInitial()) {
// Регистрация Handler'а для события LoginButtonPressed
on<LoginButtonPressed>(_onLoginButtonPressed);
}
// Сам Handler — содержит бизнес-логику
Future<void> _onLoginButtonPressed(
LoginButtonPressed event,
Emitter<AuthState> emit,
) async {
emit(AuthLoading()); // Новое состояние: загрузка
try {
final user = await authRepo.login(
email: event.email,
password: event.password,
);
emit(AuthSuccess(user)); // Новое состояние: успех
} catch (e) {
emit(AuthFailure(e.toString())); // Новое состояние: ошибка
}
}
}
Роль и характеристики Handler'а:
- Изоляция логики: Handler инкапсулирует реакцию на конкретное событие, делая код предсказуемым и тестируемым.
- Асинхронность: Часто выполняет асинхронные операции (сетевые запросы, чтение БД).
- Чистая функция (в идеале): Для данного события и текущего состояния должен возвращать детерминированное новое состояние. Побочные эффекты (навигация, показ диалогов) обычно выносятся в отдельный слой (например, BlocListener).
Где ещё встречаются Handler'ы:
- В Riverpod — это методы внутри
StateNotifierили логика внутриref.read/ref.watchв провайдерах. - В GetX — это методы внутри
GetxController. - В обработчиках жестов (
GestureDetector.onTap) или жизненного цикла (WidgetsBindingObserver).
Ответ 18+ 🔞
Блин, слушай, вот объясняю как есть. Представь, что твой Flutter-приложуха — это такой забегаловка. А Handler — это тот самый повар на кухне, который, когда официант крикнул «заказ на бургер!», начинает его, блядь, готовить. То есть, он реагирует на событие и делает всю основную работу.
Вот смотри на примере этого BLoC, там всё как на ладони. Ты жмёшь кнопку логина — это событие. А Handler — это тот кусок кода, который в этот момент просыпается и начинает орать «ёпта, работа пошла!».
// Это событие — типа крик из зала: "Эй, чел, залогинь меня!"
class LoginButtonPressed extends AuthEvent {
final String email;
final String password;
LoginButtonPressed({required this.email, required this.password});
}
// А это сам BLoC — кухня. В нём регистрируем нашего повара-хендлера.
class AuthBloc extends Bloc<AuthEvent, AuthState> {
final AuthRepository authRepo;
AuthBloc(this.authRepo) : super(AuthInitial()) {
// Вот тут говорим: когда придёт событие LoginButtonPressed, дерни-ка ты метод _onLoginButtonPressed
on<LoginButtonPressed>(_onLoginButtonPressed);
}
// А ВОТ И ОН! Сам Handler, звезда кухни, ёбаный гений логики.
Future<void> _onLoginButtonPressed(
LoginButtonPressed event,
Emitter<AuthState> emit,
) async {
emit(AuthLoading()); // Первым делом кричим на весь зал: "Ждите, ща будет!"
try {
// А теперь делаем самую важную хуйню — лезем в апишку
final user = await authRepo.login(
email: event.email,
password: event.password,
);
emit(AuthSuccess(user)); // Если всё заебись — выносим готовый заказ: "Вот ваш юзер, халявно!"
} catch (e) {
emit(AuthFailure(e.toString())); // Если всё пиздец — выносим подгоревшую хрень: "Ой, всё, ошибка!"
}
}
}
И в чём же, блядь, его сила, этого Handler'а?
- Он один за всё в ответе. Типа солдат-одиночка. Получил событие — и пошёл его ебашить. Не размазывает логику по всему коду. Тестировать его — одно удовольствие, подсовывай ему любые данные и смотри, не обосрётся ли он.
- Любит повисеть в ожидании. Часто ему надо сходить в сеть или в базу, а это, мать его, асинхронные операции. Поэтому он
asyncи делаетawait, чтобы не тормозить весь интерфейс. - В идеале — он чистюля. Дал ему одно и то же событие и состояние — получишь один и тот же результат. Как химическая реакция, ёпта. А всякие побочные эффекты вроде навигации или показа всплывашек — это уже не его епархия, для этого есть другие ребята (типа
BlocListener).
Да и вообще, чувак, они везде!
В Riverpod'е — это методы внутри StateNotifier или та логика, что в провайдерах крутится. В GetX — методы в контроллерах. Да даже обычный onTap у кнопки — это, по сути, простейший хендлер, ядрёна вошь! Всё один принцип: произошло что-то — вызови эту функцию.