stator 0.0.24 copy "stator: ^0.0.24" to clipboard
stator: ^0.0.24 copied to clipboard

Stator: Effortless Flutter State Management, Scale with Ease.

Stator #

An easy to use state management library for Flutter.

stator-logo

Example #

// Run the this example, play around with it, then take a look at the code to have a better understanding.
// Made by Jehad Hmoudah

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

void main() {
  // isDebuggingEnabled is true by default.
  // This line is here just to show that you can disable debugging.
  Stators.isDebuggingEnabled = true;
  runApp(const MyApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Stator Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      initialRoute: "/",
      routes: {
        "/": (context) => const HomePage(),
        "/profile-details": (context) => const ProfileDetails(),
        "/profile-setup": (context) => const ProfileSetup(),
      },
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("HomePage - Stator Demo"),
      ),
      body: Center(
        child: FilledButton(
          onPressed: () => Navigator.pushNamed(context, "/profile-details"),
          child: const Text("Profile Details"),
        ),
      ),
    );
  }
}

class ProfileDetailsStator with StatorMixin<ProfileDetails> {
  // You can use BehaviorSubject from RxDart or ValueNotifier instead of StateVar.
  final name = StateVar("Jehad");
  final major = StateVar("Computer Engineering");
  final age = StateVar("20");
}

class ProfileDetails extends StatefulWidget {
  const ProfileDetails({super.key});

  @override
  State<ProfileDetails> createState() => _ProfileDetailsState();
}

class _ProfileDetailsState extends State<ProfileDetails>
    with WidgetStatorMixin<ProfileDetails, ProfileDetailsStator> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("Profile Details"),
      ),
      body: Center(
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 32.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              ValueListenableBuilder(
                valueListenable: stator.name,
                builder: (context, value, child) => Text(
                  "Name: ${stator.name.value}",
                  style: Theme.of(context).textTheme.headlineSmall,
                ),
              ),
              ValueListenableBuilder(
                valueListenable: stator.major,
                builder: (context, value, child) => Text(
                  "Major: ${stator.major.value}",
                  style: Theme.of(context).textTheme.headlineSmall,
                ),
              ),
              ValueListenableBuilder(
                valueListenable: stator.age,
                builder: (context, value, child) => Text(
                  "Age: ${stator.age.value}",
                  style: Theme.of(context).textTheme.headlineSmall,
                ),
              ),
              const SizedBox(height: 10),
              SizedBox(
                width: double.infinity,
                child: FilledButton(
                  onPressed: () =>
                      Navigator.pushNamed(context, "/profile-setup"),
                  child: const Text("Profile Setup"),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

  @override
  // You can use instanceName to register multiple instances of
  // ProfileDetailsStator, e.g. if you have multiple users with
  // different IDs use the ID of each user as the instanceName.
  get config => Stator(() => ProfileDetailsStator());
}

class ProfileSetup extends StatefulWidget {
  const ProfileSetup({super.key});

  @override
  State<ProfileSetup> createState() => _ProfileSetupState();
}

class _ProfileSetupState extends State<ProfileSetup> {
  // The object ProfileDetailsStator() inside
  // useStator(() => ProfileDetailsStator()) won't be used
  // unless ProfileDetailsStator() hasn't been registered before.
  // Don't use late modifier and avoid using useStator inside initState.
  final statorOfProfileDetails = useStator(() => ProfileDetailsStator());

  // ScrollControllers must be initialized and
  // disposed inside stateful widget not inside a Stator.
  late final ScrollController scrollController;

  // TextEditingControllers can be initialized and disposed either
  // in a Stator or in a stateful widget, depending on how they
  // get used throughout the app.
  late final nameController =
  TextEditingController(text: statorOfProfileDetails.name.value);
  late final majorController =
  TextEditingController(text: statorOfProfileDetails.major.value);
  late final ageController =
  TextEditingController(text: statorOfProfileDetails.age.value);

  @override
  void initState() {
    super.initState();
    scrollController = ScrollController();
  }

  @override
  void dispose() {
    // You must disuse Stators of other screens so that automatic
    // unregistering works correctly.
    disuseStator<ProfileDetailsStator>();
    scrollController.dispose();
    nameController.dispose();
    majorController.dispose();
    ageController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () => FocusScope.of(context).unfocus(),
      child: Scaffold(
        appBar: AppBar(
          title: const Text("Profile Setup"),
        ),
        body: Center(
          child: SingleChildScrollView(
            padding: const EdgeInsets.symmetric(horizontal: 16),
            controller: scrollController,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                const Text(
                  "State/Data is synced between Profile Details screen and all Profile Setup screens.",
                  textAlign: TextAlign.center,
                ),
                const SizedBox(height: 10),
                ValueListenableBuilder(
                  builder: (context, value, child) {
                    nameController.text = statorOfProfileDetails.name.value;
                    return TextField(
                      controller: nameController,
                      decoration: const InputDecoration(
                        filled: true,
                        labelText: "Age",
                      ),
                      onChanged: (value) =>
                      statorOfProfileDetails.name.value = value,
                    );
                  },
                  valueListenable: statorOfProfileDetails.name,
                ),
                const SizedBox(height: 10),
                ValueListenableBuilder(
                  builder: (context, value, child) {
                    majorController.text = statorOfProfileDetails.major.value;
                    return TextField(
                      controller: majorController,
                      decoration: const InputDecoration(
                        filled: true,
                        labelText: "Age",
                      ),
                      onChanged: (value) =>
                      statorOfProfileDetails.major.value = value,
                    );
                  },
                  valueListenable: statorOfProfileDetails.major,
                ),
                const SizedBox(height: 10),
                ValueListenableBuilder(
                  builder: (context, value, child) {
                    ageController.text = statorOfProfileDetails.age.value;
                    return TextField(
                      controller: ageController,
                      decoration: const InputDecoration(
                        filled: true,
                        labelText: "Age",
                      ),
                      onChanged: (value) =>
                      statorOfProfileDetails.age.value = value,
                    );
                  },
                  valueListenable: statorOfProfileDetails.age,
                ),
                const SizedBox(height: 10),
                FilledButton(
                  onPressed: () =>
                      Navigator.pushNamed(context, "/profile-setup"),
                  child: const Text("Push Another Profile Setup"),
                ),
                const SizedBox(height: 10),
                const Text(
                  "Each time you push a new Profile Setup screen the widgetsUsingThisStator gets incremented.\n You can see that in your console/terminal.",
                  textAlign: TextAlign.center,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
2
likes
160
pub points
62%
popularity
screenshot

Publisher

verified publisherjehadhmoudah.com

Stator: Effortless Flutter State Management, Scale with Ease.

Homepage
Repository (GitHub)
View/report issues

Documentation

API reference

License

Apache-2.0 (LICENSE)

Dependencies

flutter, get_it

More

Packages that depend on stator