0 коментари 14 мин. читање 20 ноември, 2025

Како да го изберете вистинскиот State Management во Flutter

Flutter е моќен framework за развој на мобилни апликации, но еден од најголемите предизвици за сите кои развиваат апликации е изборот на вистинскиот state management.

State management помага во управување со податоците и UI-то на ефикасен начин, обезбедувајќи апликацијата да остане „послушна“ и лесна за одржување.

Во продолжение се најпопуларните state management решенија во Flutter, нивните предности, недостатоци и препораки според потребите на вашиот проект.

1. Provider: Едноставно решение за почетници

Provider е една од најпознатите state management библиотеки и воедно официјално препорачан од тимот на Flutter. Тој е лесен, ефикасен и едноставен за користење.

Package: provider

Предности:

  • Леснен за учење и користење
  • Препорачан од Flutter тимот
  • Одличен за мали и средни проекти

Недостатоци:

  • Не е погоден за многу комплексни апликации со повеќе состојби

Кога да користите Provider?

  • Ако штотуку почнувате со state management
  • За апликации со едноставна бизнис логика

Примери:

Креирај state

class Counter with ChangeNotifier {
  int _count = 0;

  int get count => _count;

  void increment() {
    _count++;
    notifyListeners(); // кажи му на UI да се освежи
  }
}

Регистрација на provider-от

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (_) => Counter(),
      child: MyApp(),
    ),
  );
}

Употреба го state-от во UI

class CounterWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = Provider.of<Counter>(context);

    return Column(
      children: [
        Text('Count: ${counter.count}'),
        ElevatedButton(
          onPressed: counter.increment,
          child: Text('Додај'),
        ),
      ],
    );
  }
}

2. Riverpod: Моќна замена за Provider

Riverpod е понова и подобрена верзија на Provider. Тој нуди поголема флексибилност, безбедност и полесно тестирање.

Package: flutter_riverpod

Предности:

  • Не зависи од BuildContext
  • Поголема флексибилност и безбедност
  • Одличен за тестирање и dependency injection

Недостатоци:

  • Поголема крива на учење

Кога да користите Riverpod?

  • Ако ви треба посилно решение од Provider
  • За средни и големи проекти

Примери:

Додај dependency

dependencies:
  flutter_riverpod: ^2.0.0

Дефинирај provider

import 'package:flutter_riverpod/flutter_riverpod.dart';

final counterProvider = StateProvider<int>((ref) => 0);

Употреба во UI

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

void main() {
  runApp(ProviderScope(child: MyApp())); // Wrap app with ProviderScope
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(home: HomePage());
  }
}

class HomePage extends ConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final count = ref.watch(counterProvider);

    return Scaffold(
      appBar: AppBar(title: Text('Riverpod Example')),
      body: Center(child: Text('Count: $count')),
      floatingActionButton: FloatingActionButton(
        onPressed: () => ref.read(counterProvider.notifier).state++,
        child: Icon(Icons.add),
      ),
    );
  }
}

3. Bloc: За комплексни апликации

BLoC (Business Logic Component) е архитектонски модел кој ја одвојува бизнис логиката од UI-то. Совршен е за големи апликации.

Package: flutter_bloc

Предности:

  • Јасна поделба меѓу логика и UI
  • Најдобар избор за големи enterprise апликации

Недостатоци:

  • Повеќе boilerplate код

Кога да користите Bloc?

  • За enterprise апликации
  • Кога ви треба добро структурирано решение

Примери:

Event:

abstract class CartEvent {}

class AddItemToCart extends CartEvent {
  final String productId;
  AddItemToCart(this.productId);
}

State:

abstract class CartState {}

class CartInitial extends CartState {}
class CartLoading extends CartState {}
class CartLoaded extends CartState {
  final List<String> items;
  CartLoaded(this.items);
}

Bloc:

class CartBloc extends Bloc<CartEvent, CartState> {
  List<String> _cartItems = [];

  CartBloc() : super(CartInitial()) {
    on<AddItemToCart>((event, emit) {
      emit(CartLoading());
      _cartItems.add(event.productId);
      emit(CartLoaded(List.from(_cartItems)));
    });
  }
}

Употреба во UI:

BlocBuilder<CartBloc, CartState>(
  builder: (context, state) {
    if (state is CartLoading) {
      return CircularProgressIndicator();
    } else if (state is CartLoaded) {
      return ListView(
        children: state.items.map((item) => Text(item)).toList(),
      );
    }
    return Text('Кошничката е празна');
  },
);

4. GetX: Брзо и едноставно решение

GetX е популарен поради својата едноставност, мала тежина и тоа што вклучува state management, routing и dependency injection.

Package: get

Предности:

  • Минимален boilerplate
  • Вклучува state management, навигација и dependency injection

Недостатоци:

  • Помалку структуриран за големи проекти

Кога да користите GetX?

  • За прототипови и брз развој
  • Ако сакате минимален код

Примери:

GetX има неколку начини за менаџирање:

Reactive State (Obx)

Користи Rx (Reactive) променлива, потоа го става корисничкиот интерфејс со Obx за да открие автоматски промени.

Пример
class CounterController extends GetxController {
  var count = 0.obs; // .obs make variables observable

  void increment() {
    count++;
  }
}

// UI
final controller = Get.put(CounterController());

Obx(() => Text("Count: ${controller.count}"));

Simple State (update())

Користи GetBuilder, погодно за состојба која не е многу сложена.

Пример:
class CounterController extends GetxController {
  int count = 0;

  void increment() {
    count++;
    update(); // trigger UI update
  }
}

// UI
GetBuilder<CounterController>(
  init: CounterController(),
  builder: (controller) => Text("Count: ${controller.count}"),
);

Dependency Injection

GetX исто така може многу лесно да инјектира и постави контролер.

Пример:
final controller = Get.put(CounterController()); // направено еднаш, користи насекаде

Routing

Навигирајте брзо и лесно.

Пример:
Get.to(DetailPage());
Get.back();
Get.offAll(HomePage());

5. MobX: Реактивно програмирање

MobX го носи концептот на реактивно програмирање во Flutter. Работи со observable, action, reaction и computed концепти.

Концептот на MobX јадро во Flutter:

  • Observable (State): Ова се податоци што можат да се менуваат и можат да се набљудуваат. Примери: бројачи на променливи, листи на производи, итн.
  • Action: Функции што се менуваат Observable. Сите промени на состојбата треба да бидат спакувани во акција за MobX да може јасно да ги следи промените.
  • Reaction: Несакани ефекти што се извршуваат кога се менуваат видливите вредности. На пример, повторно градење на корисничкиот интерфејс кога се менуваат податоците.
  • Computed: Вредности пресметани од други видливите вредности. Пример: isCartEmpty може да се пресмета од cartItems.isEmpty.

Package: mobx, flutter_mobx

Предности:

  • Многу реактивно
  • Чист и мал boilerplate

Недостатоци:

  • Бара build_runner и code generation

Како функционира:

Ја означувате променливата како @observable, потоа ја менувате вредноста преку @action, а корисничкиот интерфејс автоматски ќе се изгради одново ако користите Observer.

Примери:

Додај Dependency:

dependencies:
  flutter_mobx: ^2.0.6
  mobx: ^2.0.6

dev_dependencies:
  build_runner: ^2.1.7
  mobx_codegen: ^2.0.5

Креирај state:

import 'package:mobx/mobx.dart';
part 'counter_store.g.dart';

class CounterStore = _CounterStore with _$CounterStore;

abstract class _CounterStore with Store {
@observable
int counter = 0;

@action
void increment() {
counter++;
}
}

Потоа изврши ја командата:

flutter pub run build_runner build

Употреба во UI:

final counterStore = CounterStore();

Observer(
  builder: (_) => Text('${counterStore.counter}'),
)

ElevatedButton(
  onPressed: () => counterStore.increment(),
  child: Text('Изврши'),
)

6. Redux: Централизирано управување

Redux во Flutter е шема за управување со состојби адаптирана од Redux во JavaScript (особено React). Тој се фокусира на концептот на еден извор на вистина (single source of truth), состојба што не може да се промени директно (immutable) и еднонасочен проток на податоци (unidirectional flow).

Основен концепт на Redux:

  • Store: Каде што се чуваат сите состојби. Постои само едно главно складиште.
  • State: Претставување на сите податоци од вашата апликација. Состојбата е immutable, па затоа не треба да се менува директно.
  • Action: Објекти што опишуваат што сакаат да прават (на пр.: { тип: ‘ADD_TODO’ }).
  • Reducer: Функции што прифаќаат состојба и акција, а потоа ја враќаат новата состојба.
  • Middleware (опционално): Места за справување со несакани ефекти како што се API повици, евидентирање итн.

Redux Flow:

UI (View)

Dispatch (Action)

Reducer (reducer state)

Store (update state)

Rebuild UI reduce an update state

Пакет: flutter_redux

Предности:

  • Погодно за сложени проекти
  • Олеснување на дебагирање со предвидливи системи

Недостатоци:

  • Boilerplate е висок

Кога да се користи Redux?

  • Ако ви е потребно многу структурирано управување со состојби
  • За апликации со многу споделени состојби

Примери:

Додај dependency

dependencies:
  flutter_redux: ^0.10.0
  redux: ^5.0.0

Дефинирање на State

class CounterState {
  final int count;
  CounterState(this.count);
}

Дефинирање на action

class IncrementAction {}

Креирај Reducer

CounterState counterReducer(CounterState state, dynamic action) {
  if (action is IncrementAction) {
    return CounterState(state.count + 1);
  }
  return state;
}

Креирај State

final store = Store<CounterState>(
  counterReducer,
  initialState: CounterState(0),
);

Употреба во UI

void main() {
  runApp(MyApp(store: store));
}

class MyApp extends StatelessWidget {
  final Store<CounterState> store;

  MyApp({required this.store});

  @override
  Widget build(BuildContext context) {
    return StoreProvider(
      store: store,
      child: MaterialApp(
        home: CounterPage(),
      ),
    );
  }
}

class CounterPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: StoreConnector<CounterState, int>(
          converter: (store) => store.state.count,
          builder: (context, count) => Text('$count'),
        ),
      ),
      floatingActionButton: StoreConnector<CounterState, VoidCallback>(
        converter: (store) => () => store.dispatch(IncrementAction()),
        builder: (context, callback) => FloatingActionButton(
          onPressed: callback,
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

Заклучок: Што да изберете?

ПотребаПрепорачан State Management
Почетници / мали проектиProvider / GetX
Средни и големи проектиRiverpod / Bloc
Реактивно програмирањеMobX
Централизиран stateRedux
Брз прототипингGetX

Совети:

  • Започнете со Provider или Riverpod ако сте почетници.
  • Изберете Bloc или Riverpod за големи, добро структуриран проекти.
  • Користете GetX за брз развој.

Со вистинскиот избор на state management, ќе го подобрите одржувањето, перформансите и скалабилноста на вашата Flutter апликација.

Среќно програмирање!

Avatar photo
Напишано од

Мартин Рајовски

Јас сум програмер и администратор на форум. Кога не сум зафатен со решавање кодови или смирување форумски драми, обожавам да играм пинг-понг (барем мислам дека знам). Голем фан сум на тетоважи и опседнат со руската култура. Технолошки фанатик по ден, фотографски ентузијаст по ноќ – со други зборови, секогаш на лов по нова генијална идеја или совршена фотка!

Сите написи од овој автор
Добивај известувања
Извести ме за
guest
0 Коментари
Најнови
Најстари Со највеќе гласови
Мени
Заедница
Изглед
To top