flutter_mediator_lite 1.0.2+2
flutter_mediator_lite: ^1.0.2+2 copied to clipboard

A super easy state management package, base on the InheritedModel with automatic aspect management.

Flutter Mediator Lite #

Flutter Mediator pub.dev License Build Status Global Mode + Model Mode
Lite pub.dev License Build Status Global Mode only
Persistence pub.dev License Build Status Lite + Persistence
Example Logins to a REST server with i18n, theming, persistence and state management.

Flutter Mediator Lite is a super easy state management package, base on the InheritedModel with automatic aspect management to make it simpler and easier to use and rebuild widgets only when necessary.

Flutter Mediator Lite is derived from Flutter Mediator v2.1.3, and consists only of the Global Mode.



Table of Contents #


Setting up #

Add the following dependency to pubspec.yaml of your flutter project:

dependencies:
  flutter_mediator_lite: "^1.0.2"

Import flutter_mediator_lite in files that will be used:

import 'package:flutter_mediator_lite/mediator.dart';

For help getting started with Flutter, view the online documentation.

Table of Contents

Steps #

  1. Declare the watched variable with globalWatch.
    Suggest to put the watched variables into a file var.dart and then import it.

  2. Create the host with globalHost at the top of the widget tree.

  3. Create a widget with globalConsume or watchedVar.consume to register the watched variable to the host to rebuild it when updating.

  4. Make an update to the watched variable, by watchedVar.value or watchedVar.ob.updateMethod(...).

Table of Contents

Case 1: Int #

example/lib/main.dart

Step 1: var.dart

//* Step1: Declare the watched variable with `globalWatch`
//* in the var.dart and then import it.
final touchCount = globalWatch(0);

Step 2:

Future<void> main() async {
  //* Initialize the persistent watched variables
  //* whose value is stored by the SharedPreferences.
  await initVars();

  runApp(
    //* Step2: Create the host with `globalHost`
    //* at the top of the widget tree.
    globalHost(
      child: MyApp(),
    ),
  );
}

Step 3:

Scaffold(
  appBar: AppBar(title: const Text('Int Demo')),
  body: Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      const Text('You have pushed the button this many times:'),
      //* Step3: Create a widget with `globalConsume` or `watchedVar.consume`
      //* to register the watched variable to the host to rebuild it when updating.
      globalConsume(
        () => Text(
          '${touchCount.value}',
          style: Theme.of(context).textTheme.headline4,
        ),
      ),
   // ...

Step 4:

FloatingActionButton(
  //* Stet4: Make an update to the watched variable.
  onPressed: () => touchCount.value++,
  tooltip: 'Increment',
  child: const Icon(Icons.add),
  heroTag: null,
),

Table of Contents

Case 2: List #

example/lib/pages/list_page.dart

Step 1: var.dart

//* Step1: Declare the watched variable with `globalWatch` in the var.dart.
//* And then import it in the file.
final data = globalWatch(<ListItem>[]);

Step 3:

return Scaffold(
  appBar: AppBar(title: const Text('List Demo')),
  //* Step3: Create a widget with `globalConsume` or `watchedVar.consume`
  //* to register the watched variable to the host to rebuild it when updating.
  body: globalConsume(
    () => GridView.builder(
      itemCount: data.value.length,

    // ...

Step 4:

void updateListItem() {
  // ...

  //* Step4: Make an update to the watched variable.
  //* watchedVar.ob = watchedVar.notify() and then return the underlying object
  data.ob.add(ListItem(itemName, units, color));
}

Table of Contents

Case 3: Locale setting with Persistence by SharedPreferences #

Or use Flutter Mediator Persistence for built in persistence support.
Please see Flutter Mediator Persistence: use case 3 for details.

example/lib/pages/locale_page.dart

Step 1-1: var.dart

//* Declare a global scope SharedPreferences.
late SharedPreferences prefs;

//* Step1B: Declare the persistent watched variable with `late Rx<Type>`
//* And then import it in the file.
const DefaultLocale = 'en';
late Rx<String> locale; // local_page.dart

/// Initialize the persistent watched variables
/// whose value is stored by the SharedPreferences.
Future<void> initVars() async {
  // To make sure SharedPreferences works.
  WidgetsFlutterBinding.ensureInitialized();

  prefs = await SharedPreferences.getInstance();
  locale = globalWatch(prefs.getString('locale') ?? DefaultLocale);
}

Step 1-2: main.dart

Future<void> main() async {
  //* Step1-2: Initialize the persistent watched variables
  //* whose value is stored by the SharedPreferences.
  await initVars();

  runApp(
    // ...
  );
}

Step 1-3: main.dart

//* Initialize the locale with the persistent value.
localizationsDelegates: [
  FlutterI18nDelegate(
    translationLoader: FileTranslationLoader(
      forcedLocale: Locale(locale.value),
      fallbackFile: DefaultLocale,
      // ...
    ),
    // ...
  ),
],

Step 3:

return SizedBox(
  child: Row(
    children: [
      //* Step3: Create a widget with `globalConsume` or `watchedVar.consume`
      //* to register the watched variable to the host to rebuild it when updating.
      //* `watchedVar.consume()` is a helper function to
      //* `touch()` itself first and then `globalConsume`.
      locale.consume(() => Text('${'app.hello'.i18n(context)} ')),
      Text('$name, '),

      // ...
    ],
  ),
);

Step 4: var.dart

Future<void> changeLocale(BuildContext context, String countryCode) async {
  final loc = Locale(countryCode);
  await FlutterI18n.refresh(context, loc);
  //* Step4: Make an update to the watched variable.
  locale.value = countryCode;

  await prefs.setString('locale', countryCode);
}

Table of Contents

Case 4: Scrolling effect #

example/lib/pages/scroll_page.dart

Step 1: var.dart

//* Step1: Declare the watched variable with `globalWatch` in the var.dart.
//* And then import it in the file.
final opacityValue = globalWatch(0.0);

Step 3:

class CustomAppBar extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //* Step3: Create a widget with `globalConsume` or `watchedVar.consume`
    //* to register the watched variable to the host to rebuild it when updating.
    return globalConsume(
      () => Container(
        color: Colors.black.withOpacity(opacityValue.value),
        // ...
      ),
    );
  }
}

Step 4:

class _ScrollPageState extends State<ScrollPage> {
  // ...

  @override
  void initState() {
    _scrollController.addListener(() {
      //* Step4: Make an update to the watched variable.
      opacityValue.value =
          (_scrollController.offset / 350).clamp(0, 1).toDouble();
    });
    super.initState();
  }

Table of Contents

Recap #

  • At step 1, globalWatch(variable) creates a watched variable from the variable.

  • At step 3, create a widget and register it to the host to rebuild it when updating,
    use globalConsume(() => widget) if the value of the watched variable is used inside the widget;
    or use watchedVar.consume(() => widget) to touch() the watched variable itself first and then globalConsume(() => widget).

  • At step 4, update to the watchedVar.value will notify the host to rebuild; or the underlying object would be a class, then use watchedVar.ob.updateMethod(...) to notify the host to rebuild.
    watchedVar.ob = watchedVar.notify() and then return the underlying object.

Table of Contents

Global Get #

globalGet<T>({Object? tag}) to retrieve the watched variable from another file.

  • With globalWatch(variable), the watched variable will be retrieved by the Type of the variable, i.e. retrieve by globalGet<Type>().

  • With globalWatch(variable, tag: object), the watched variable will be retrieved by the tag, i.e. retrieve by globalGet(tag: object).

Table of Contents

Case 1: By Type #

//* Step1: Declare the watched variable with `globalWatch`.
final touchCount = globalWatch(0);

lib/pages/locale_page.dart example/lib/pages/locale_page.dart

class LocalePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //* Get the watched variable by it's [Type] from `../main.dart`
    final mainInt = globalGet<int>();

    return Container(
      // ...
          const SizedBox(height: 25),
          //* `globalConsume` the watched variable from `../main.dart`
          globalConsume(
            () => Text(
              'You have pressed the button at the first page ${mainInt.value} times',
            ),
      // ...

Table of Contents

Case 2: By tag #

//* Step1: Declare the watched variable with `globalWatch`.
final touchCount = globalWatch(0, tag: 'tagCount');

lib/pages/locale_page.dart example/lib/pages/locale_page.dart

class LocalePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    //* Get the watched variable by [tag] from `../main.dart`
    final mainInt = globalGet('tagCount');

    return Container(
      // ...
          const SizedBox(height: 25),
          //* `globalConsume` the watched variable from `../main.dart`
          globalConsume(
            () => Text(
              'You have pressed the button at the first page ${mainInt.value} times',
            ),
      // ...

Note #

  • Make sure the watched variable is initialized, only after the page is loaded.

  • When using Type to retrieve the watched variable, only the first one of the Type is returned.

Or put the watched variables into a file and then import it.

Table of Contents

Global Broadcast #

  • globalBroadcast(), to broadcast to all the globalConsume widgets.
  • globalConsumeAll(Widget Function() create, {Key? key}), to create a widget which will be rebuilt whenever any watched variables changes are made.
  • globalFrameAspects, a getter, to return the updated aspects.
  • globalAllAspects, a getter, to return all the aspects that has been registered.

Table of Contents

Versions #

Table of Contents

Example: Logins to a REST server #

A boilerplate example that logins to a REST server with i18n, theming, persistence and state management.

Please see the login to a REST server example for details.

Table of Contents


Flow chart #

Updating:


Flutter Widget of the Week: InheritedModel explained #

InheritedModel provides an aspect parameter to its descendants to indicate which fields they care about to determine whether that widget needs to rebuild. InheritedModel can help you rebuild its descendants only when necessary.

Flutter Widget of the Week: InheritedModel Explained

Changelog #

Please see the Changelog page.


License #

Flutter Mediator Lite is distributed under the MIT License. See LICENSE for more information.

Table of Contents

2
likes
130
pub points
2%
popularity

A super easy state management package, base on the InheritedModel with automatic aspect management.

Repository (GitHub)
View/report issues

Documentation

API reference

Uploader

rob333.2005@gmail.com

License

MIT (LICENSE)

Dependencies

flutter

More

Packages that depend on flutter_mediator_lite