-
Before I go reinventing the wheel I wanted to get your ideas how would you solve https://github.com/rodydavis/signals.dart/blob/main/examples/persist_shared_preferences/lib/main.dart with state_beacon? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments
-
On a cursory glance, that should be a 1 to 1 translation. I'll run it and report back. |
Beta Was this translation helpful? Give feedback.
-
Here is the state_beacon version. import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:state_beacon/state_beacon.dart';
class Settings {
Settings(this.prefs);
final SharedPreferences prefs;
final List<VoidCallback> _cleanup = [];
WritableBeacon<T> _setting<T>(
String key, {
required T Function(String) get,
required void Function(String, T?) set,
}) {
final s = Beacon.writable<T>(get(key));
_cleanup.add(s.subscribe((val) => set(key, val)));
return s;
}
late WritableBeacon<int> counter = _setting(
'counter',
get: (key) => prefs.getInt(key) ?? 0,
set: (key, val) {
if (val == null) {
prefs.remove(key);
} else {
prefs.setInt(key, val);
}
},
);
late WritableBeacon<ThemeMode> themeMode = _setting(
'theme-mode',
get: (key) => ThemeMode.values[prefs.getInt(key) ?? ThemeMode.system.index],
set: (key, val) {
if (val == null) {
prefs.remove(key);
} else {
prefs.setInt(key, val.index);
}
},
);
late WritableBeacon<String?> userId = _setting(
'user-id',
get: (key) => prefs.getString(key),
set: (key, val) {
if (val == null) {
prefs.remove(key);
} else {
prefs.setString(key, val);
}
},
);
late WritableBeacon<bool> demoMode = _setting(
'demo-mode',
get: (key) => prefs.getBool(key) ?? false,
set: (key, val) {
if (val == null) {
prefs.remove(key);
} else {
prefs.setBool(key, val);
}
},
);
void dispose() {
for (final cb in _cleanup) {
cb();
}
}
}
late final Settings settings;
void main() async {
WidgetsFlutterBinding.ensureInitialized();
final prefs = await SharedPreferences.getInstance();
settings = Settings(prefs);
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter Demo',
theme: ThemeData.light(),
darkTheme: ThemeData.dark(),
themeMode: settings.themeMode.watch(context),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatelessWidget {
const MyHomePage({super.key, required this.title});
final String title;
void _incrementCounter() {
settings.counter.value++;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(title),
actions: [
IconButton(
tooltip: 'Reset Counter',
onPressed: () => settings.counter.value = 0,
icon: const Icon(Icons.restore),
),
PopupMenuButton<ThemeMode>(
initialValue: settings.themeMode.watch(context),
itemBuilder: (context) => const [
PopupMenuItem(
value: ThemeMode.system,
child: Text('System Brightness'),
),
PopupMenuItem(
value: ThemeMode.light,
child: Text('Light Mode'),
),
PopupMenuItem(
value: ThemeMode.dark,
child: Text('Dark Mode'),
),
],
onSelected: settings.themeMode.set,
),
],
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text(
'You have pushed the button this many times:',
),
Text(
'${settings.counter.watch(context)}',
style: Theme.of(context).textTheme.headlineMedium,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
} |
Beta Was this translation helpful? Give feedback.
-
FWIW, this is how I'd architect it. This makes it easier to add/remove keys. class Settings extends BeaconController {
Settings(this.prefs);
final SharedPreferences prefs;
WritableBeacon<int> _intSetting(String key) {
final b = B.writable<int>(prefs.getInt(key) ?? 0);
b.subscribe((val) => prefs.setInt(key, val));
return b;
}
WritableBeacon<String?> _stringSetting(String key) {
final b = B.writable<String>(prefs.getString(key) ?? '');
b.subscribe((val) => prefs.setString(key, val));
return b;
}
WritableBeacon<bool> _boolSetting(String key) {
final b = B.writable<bool>(prefs.getBool(key) ?? false);
b.subscribe((val) => prefs.setBool(key, val));
return b;
}
WritableBeacon<T> _customSetting<T>(
String key, {
required T Function(String) get,
required void Function(String, T?) set,
}) {
final b = B.writable(get(key));
b.subscribe((val) => set(key, val));
return b;
}
late final counter = _intSetting('counter');
late final userName = _stringSetting('user-id');
late final demoMode = _boolSetting('demo-mode');
late final themeMode = _customSetting(
'theme-mode',
get: (key) => ThemeMode.values[prefs.getInt(key) ?? ThemeMode.system.index],
set: (key, val) {
if (val == null) {
prefs.remove(key);
} else {
prefs.setInt(key, val.index);
}
},
);
} |
Beta Was this translation helpful? Give feedback.
FWIW, this is how I'd architect it. This makes it easier to add/remove keys.