flutter_mediator_simple 1.0.3
flutter_mediator_simple: ^1.0.3 copied to clipboard
A state management package for flutter. Simple, efficient and easy to use.
Flutter Mediator Simple #
| Flutter Mediator Simple |
|
|
|
A rework of the Flutter Mediator, simple, efficient and easy to use. |
Flutter Mediator Simple is a state management package for flutter. Simple, efficient and easy to use.
Table of Contents #
Setting up #
Add the following dependency to pubspec.yaml of the flutter app.
dependencies:
flutter_mediator_simple: "^1.0.3"
Import flutter_mediator_simple in files that will be used:
import 'package:flutter_mediator_simple/flutter_mediator_simple.dart';
For help getting started with Flutter, view the online documentation.
How to use #
-
Declare variable which needs to be managed with
.rxsuffix, to make it a mediator variable.
Suggest to put mediator variables into the file var.dart and then import it(with show, hide capability of the import). -
Create
Subscriberwidgets. Any mediator variables used inside theSubscriberwidget will automatically rebuild the widget when updated.
Use Case 1: Mediator Variable of type Int #
Step 1: Declare a mediator variable _int1 in var.dart.
// Mediator Variable: int1
final _int1 = 0.rx; // or `final _int1 = Rx(0);`
int get int1 => _int1.value;
set int1(value) => _int1.value = value;
// optional
get int1Subscribe => _int1.subscribe;
String get int1Notify => _int1.notify;
Step 2: Create a Subscriber widget using int1 which is _int1.value.
Subscriber(
builder: () {
return Text(
'int1: $int1', // using the `_int1` mediator variable
style: Theme.of(context).textTheme.headlineMedium,
);
},
),
Update int1 => rebuild automatically.
@override
Widget build(BuildContext context) {
return DefaultTabController(
initialIndex: 0,
length: myTabs.length,
child: Scaffold(
// ...
floatingActionButton: FloatingActionButton(
onPressed: () {
switch (_tabController.index) {
case 0:
int1++;
break;
case 1:
int2++;
break;
case 2:
int3++;
break;
case 3:
updateListItem();
break;
case 4:
int1++;
break;
default:
}
},
// ...
),
),
);
Use Case 2: Mediator Variable of type List #
Step 1: Declare a mediator variable _data in var.dart.
// Mediator Variable: data
final _data = <ListItem>[].rx; //or `RxList(<ListItem>[]);`
List<ListItem> get data => _data.value;
set data(List<ListItem> value) => _data.value = value;
SubscriberFn get dataSubscribe => _data.subscribe;
List<ListItem> get dataNotify => _data.notify;
Step 2: Create a Subscriber widget using data which is _data.value.
return Scaffold(
appBar: AppBar(title: const Text('List Demo')),
//* Step: Create Subscriber widget
body: Subscriber(
builder: () => GridView.builder(
itemCount: data.length, // using the `_data` mediator variable
// ...
Step 3: Implement an update function of data.
void updateListItem() {
final units = Random().nextInt(maxUnits) + 1;
final itemIdx = Random().nextInt(itemNames.length);
final itemName = itemNames[itemIdx];
final color = itemColors[Random().nextInt(itemColors.length)];
if (data.length >= maxItems) data.clear();
//* Make an update to the collection type mediator variable.
// data.add(ListItem(itemName, units, color));
_data.notify.add(ListItem(itemName, units, color)); // notify the widget to rebuild
}
Use notify to notify the Subscribe widget to rebuild when the mediator variable is updated.
Use Case 3: Indirect use of Mediator Variable and Persistence #
Indirect use means the Subscriber widget doesn't use the value of the mediator variable but depends on it.
Step 1: Install i18n package flutter_i18n and follow the instructions to set it up.
Step 1-1: Setup locale delegates in main.dart.
return MaterialApp(
// ...
// add flutter_i18n support
localizationsDelegates: [
FlutterI18nDelegate(
translationLoader: FileTranslationLoader(
forcedLocale: Locale(locale),
// useCountryCode: true,
fallbackFile: 'en',
basePath: 'assets/flutter_i18n',
decodeStrategies: [JsonDecodeStrategy()],
),
missingTranslationHandler: (key, locale) {
// ignore: avoid_print
print(
'--- Missing Key: $key, languageCode: ${locale!.languageCode}');
},
),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
);
Step 1-2: Add assets in pubspec.yaml and prepare locale files in that folder
# pubspec.yaml
flutter:
assets:
- assets/flutter_i18n/
Step 2: Install the persistence package shared_preferences
Step 3: Declare a mediator variable _locale and SharedPreferences in var.dart.
/// Locale page
late SharedPreferences prefs; // for persistence
// Mediator Variable: locale
late Rx<String> _locale;
String get locale => _locale.value;
// set locale(String value) => _locale.value = value; // comment out
get localeSubscribe => _locale.subscribe;
String get localeNotify => _locale.notify;
Step 4: Implement a function to initial the persistence.
initPersistence() async {
WidgetsFlutterBinding.ensureInitialized(); // for shared_Preferences
prefs = await SharedPreferences.getInstance();
final loc = prefs.getString("locale") ?? 'en'; // default locale to 'en'
_locale = loc.rx; // make _locale a mediator variable of type `Rx<String>`
}
Step 5: Implement setter of _locale to use persistence.
set locale(String value) {
_locale.value = value;
prefs.setString("locale", value);
}
Step 6: Implement a function to change locale.
/// Change the locale, by `String`[countryCode]
Future<void> changeLocale(BuildContext context, String countryCode) async {
if (countryCode != locale) {
final loc = Locale(countryCode);
await FlutterI18n.refresh(context, loc);
locale = countryCode; // Rebuild associate Subscriber widgets.
}
}
Step 7: Initial the persistence in main.dart.
void main() async {
await initPersistence();
runApp(const MyApp());
}
Step 8(optional): Implement extensions on String to help building Subscriber widget of locale in var.dart.
extension StringI18n on String {
/// String extension for i18n.
String i18n(BuildContext context) {
return FlutterI18n.translate(context, this);
}
/// String extension for i18n
/// use `_locale.subscribe` to create Subscriber widget of locale.
Widget sub18n(BuildContext context, {TextStyle? style}) {
return _locale.subscribe(
() => Text(FlutterI18n.translate(context, this), style: style),
);
}
}
Step 9: Create Subscriber widgets of locale in main.dart.
Widget localeTxt(BuildContext context, String name) {
return SizedBox(
width: 250,
child: Row(
children: [
//* Step: Create a Subscriber widget
localeSubscribe(() => Text('${'app.hello'.i18n(context)} ')),
Text('$name, '),
//* Or use the string extension `sub18n`(in var.dart)
'app.thanks'.sub18n(context),
],
),
);
}
Step 10: Handle radio status to change locale in class _RadioGroupState at main.dart.
Future<void> _handleRadioValueChange1(Object? value) async {
await changeLocale(context, value!.toString());
setState(() {});
}
subscribe #
To create a Subscriber widget for indirect use of the mediator variable.
Indirect use means the Subscriber widget doesn't use the value of the mediator variable but depends on it.
For example, the locale use case.
notify #
Notify to rebuild with the aspects of the mediator variable.
Used when the type of the mediator variable is of type Class.
Mediator variable uses setter to automatically notify the rebuild. When it comes to a class variable and adds item by method, then notify is needed to inform the rebuild.
VS Code Snippet #
Use VS Code snippet to help typing the boilerplates. Take for example snippet_Flutter_Mediator__statelessful.code-snippets,
{
"Getter/Setter for Flutter Mediator": {
"prefix": "getset",
"body": [
"// Mediator Variable: ${1:var}",
"final _${1:var} = ${2:initialValue}.rx;",
"${3:type} get $1 => _${1:var}.value;",
"set $1(${3:type} value) => _${1:var}.value = value;",
"SubscriberFn get ${1:var}Subscribe => _${1:var}.subscribe;",
"${3:type} get ${1:var}Notify => _${1:var}.notify;",
"$0"
],
"description": "Getter/Setter for Flutter Mediator"
},
"Create a Subscriber Widget (Arrow Function)": {
"prefix": "sub1",
"body": [
"${1:Subscriber}(",
"\tbuilder: () => ${2:Text}(\"$3\"),",
"),",
"$0"
],
"description": "Create a Subscriber Widget (Arrow Function)"
},
"Create a Subscriber Widget (Multiline)": {
"prefix": "subs",
"body": [
"${1:Subscriber}(",
"\tbuilder: () {",
"\t\treturn ${2:Text}(\"$3\");",
"\t},",
"),",
"$0"
],
"description": "Create a Subscriber Widget (Multiline)"
}
}
State Management with Animation #
By using flutter_animate, animation can easily add to the mediator variable. If animation is needed every time the mediator variable changes, just add a ValueKey to the animate. For example, example/lib/main.dart
Subscriber(
builder: () {
return Text(
'int1: $int1', // using the `_int1` mediator variable
style: Theme.of(context).textTheme.headlineMedium,
)
.animate(key: ValueKey(int1))
.fade(duration: 125.ms)
.scale(delay: 125.ms);
},
Changelog #
Please see the Changelog page.
License #
Flutter Mediator Simple is distributed under the MIT License. See LICENSE for more information.