state_flow 0.0.3 copy "state_flow: ^0.0.3" to clipboard
state_flow: ^0.0.3 copied to clipboard

StateFlow provides a simple and efficient way to manage state in your Flutter applications.

StateFlow: State Management #

StateFlow provides a simple and efficient way to manage state in your Flutter applications. This guide will walk you through the core concepts and usage of StateFlow's state management features.

Core Concepts #

StateFlow's state management is built around these key concepts:

  • StateFlowController: A base class for creating controllers that manage application logic and state.
  • take(): A reactive value holder that notifies listeners when its value changes.
  • StateFlowApp: A widget that sets up the StateFlow environment and dependency injection.
  • StateValueBuilder: A widget that rebuilds when specified states change.

Setting Up #

Add the dependency to your pubspec.yaml file:

dependencies:
  state_flow: ^0.0.3

Wrap your app with StateFlowApp to enable the StateFlow functionality. Make sure to pass the controllers you want to use in the controllers parameter.

void main() {
  runApp(StateFlowApp(
    controllers: [
      () => CounterController(),
    ],
    child: MyApp(),
  ));
}

Creating Controllers #

Controllers are the core of StateFlow's state management. They manage application logic and state, and can be used to create reactive UIs.

To create a controller, extend StateFlowController:

Declare Variables

  // int
  final counter = take(0);
  // String
  final name = take('');
  // bool
  final isLoading = take(false);
  // List
  final todos = take([]);
  // Map
  final user = take({});
  // Object
  final user = take(User());

class CounterController extends StateFlowController {
  final counter = take(0);

  void increment() {
    counter.value++;
  }
}

Using StateValueBuilder #

final counterController = listen(CounterController)

StateValueBuilder(
  value: counterController.counter,
  builder: (value) => Text('Counter: $value'),
),

Networking #

StateFlow provides networking features using the StateFlowClient.

Use the StateFlowClient #

At first you need to create a StateFlowClient. This is used to send requests to the server.

final client = StateFlowClient(baseUrl: 'example.com');

final response = await client.sendRequest('/todos', HttpMethod.GET);

HttpMethod #

You use these methods to send requests to the server.

enum HttpMethod {
  GET,
  POST,
  PUT,
  DELETE,
}

Creating a Network Controller #

To create a network controller, extend StateFlowController: If you want to use the Controller to fetch data or or perform any kind of logic then you can extend StateFlowController with your normal controller.

class TodoController extends StateFlowController {
  final todos = take<List<Todo>>([]);
  // Base url for the api
  final StateFlowClient _client =
      StateFlowClient(baseUrl: 'example.com');

  Future<List<Todo>> fetchTodos() async {
    // Set the state to loading
    todos.setLoading();
    try {
      final response = await _client.sendRequest('/todos', HttpMethod.GET);
      if (response.statusCode == 200) {
        // Set the state to loaded
        final List<dynamic> jsonData = jsonDecode(response.body);
        final todoList = jsonData.map((json) => Todo.fromJson(json)).toList();
        // Set the state to loaded
        todos.setLoaded(todoList);
        return todos.value;
      } else {
        // Set the state to error
        todos.setError('Failed to load todos');
        return [];
      }
    } catch (e) {
      // Set the state to error
      todos.setError(e);
      todos.stopLoading();
      rethrow;
    }
  }
}

Building Reactive UI #

You can use the listen function to listen to the state of the controller. If you want to build a widget that rebuilds when the state changes, you can use the WidgetStateValueBuilder widget.

final todoController = listen(TodoController);

    WidgetStateValueBuilder<List<Todo>>(
              state: todoController.todos,
              dataBuilder: (data) {
                if (data.isEmpty) {
                  return Text('No todos');
                }
                return Expanded(
                  child: ListView.builder(
                    itemCount: data.length,
                    itemBuilder: (context, index) {
                      return ListTile(
                        title: Text(data[index].title),
                      );
                    },
                  ),
                );
              },
              errorBuilder: (error) => Text('Error: ${error.toString()}'),
              loadingBuilder: () => CircularProgressIndicator(),
            ),

Animation Controller #

If you want to use the animation controller without StateFulWidget, you can use the takeAnimationController function.

class TestApp extends StatelessWidget {
  const TestApp({super.key});

  @override
  Widget build(BuildContext context) {
    final animationController = takeAnimationController();
    return const Placeholder();
  }
}

StateFlowWidget #

If you want to use initState and disposeState to be called, you can use StateFlowWidget.

class TestApp extends StateFlowWidget {
  TestApp({super.key}) : super();
   @override
  void onInit(context) {
    print('TestApp onInit');
  }

  @override
  void onDispose() {
    print('TestApp onDispose');
  }
  @override
  Widget build(BuildContext context) {
    return const Placeholder();
  }
}

StateFlow Navigation #

For enabling navigation in your app, you can use the navigatorKey: StateFlow.navigatorKey in your MaterialApp.

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'StateFlow Demo',
      navigatorKey: StateFlow.navigatorKey,
      theme: ThemeData(primarySwatch: Colors.blue),
    );
  }
}

Use the StateFlow.to method to navigate to a new screen.

StateFlow.to(DetailScreen());

For going back to the previous screen, you can use the StateFlow.back method.

StateFlow.back();
StateFlow.off(DetailScreen());
StateFlow.offAll(DetailScreen());
StateFlow.maybePop();
StateFlow.currentRoute();
StateFlow.getHistory();
 onGenerateRoute: (settings) => StateFlow.onGenerateRoute(settings),

You can create your App Routes like this

class AppRoutes {
  static const String home = '/';
  static const String second = '/second';

  static final routes = {
    home: (context) => HomeScreen(),
    second: (context) => SecondScreen(),
  };
}

Modify the MaterialApp like this use onGenerateRoute: (settings) => StateFlow.onGenerateRoute(settings), routes: AppRoutes.routes and navigatorKey: StateFlow.navigatorKey

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'StateFlow Demo',
      navigatorKey: StateFlow.navigatorKey,
      onGenerateRoute: (settings) => StateFlow.onGenerateRoute(settings),
      theme: ThemeData(primarySwatch: Colors.blue),
      routes: AppRoutes.routes,
    );
  }
}

Now You can use with your routes

onPressed: () => StateFlow.to('/second')
onPressed: () => StateFlow.to(AppRoutes.second)
5
likes
130
pub points
0%
popularity

Publisher

verified publishernimusoftlabs.com

StateFlow provides a simple and efficient way to manage state in your Flutter applications.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter

More

Packages that depend on state_flow