Skip to content

Commit 494dbd6

Browse files
committed
add the $ alias for value
add autosave feature handle and edge case where value was updated during flutter widget build phase, and shared value subscribed widgets were not notified later update example app 0.3.0
1 parent c068081 commit 494dbd6

File tree

9 files changed

+82
-72
lines changed

9 files changed

+82
-72
lines changed

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ class MyWidgetState extends State<MyWidget> {
3535
@override
3636
Widget build(BuildContext context) {
3737
38-
// supply [counter] the `BuildContext` to rebuild widget
39-
counterValue = counter.of(context);
38+
// The .of(context) bit makes this widget rebuild everytime counter is changed
39+
int counterValue = counter.of(context);
4040
4141
return Text("Counter: $counterValue");
4242
}
@@ -59,5 +59,3 @@ await counter.load();
5959
## Efficiency
6060

6161
Shared value is smart enough to only rebuild the widget that is using the shared value that was updated. No more, no less.
62-
63-

example/android/app/src/main/AndroidManifest.xml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
additional functionality it is fine to subclass or reimplement
88
FlutterApplication and put your custom class here. -->
99
<application
10-
android:name="io.flutter.app.FlutterApplication"
1110
android:label="example"
1211
android:icon="@mipmap/ic_launcher">
1312
<activity
@@ -25,9 +24,12 @@
2524
android:name="io.flutter.app.android.SplashScreenUntilFirstFrame"
2625
android:value="true" />
2726
<intent-filter>
28-
<action android:name="android.intent.action.MAIN"/>
29-
<category android:name="android.intent.category.LAUNCHER"/>
27+
<action android:name="android.intent.action.MAIN" />
28+
<category android:name="android.intent.category.LAUNCHER" />
3029
</intent-filter>
3130
</activity>
31+
<meta-data
32+
android:name="flutterEmbedding"
33+
android:value="2" />
3234
</application>
3335
</manifest>
Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,5 @@
11
package scientifichackers.com.example
22

3-
import android.os.Bundle
3+
import io.flutter.embedding.android.FlutterActivity
44

5-
import io.flutter.app.FlutterActivity
6-
import io.flutter.plugins.GeneratedPluginRegistrant
7-
8-
class MainActivity: FlutterActivity() {
9-
override fun onCreate(savedInstanceState: Bundle?) {
10-
super.onCreate(savedInstanceState)
11-
GeneratedPluginRegistrant.registerWith(this)
12-
}
13-
}
5+
class MainActivity : FlutterActivity() {}

example/lib/main.dart

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import 'package:flutter/material.dart';
22
import 'package:shared_value/shared_value.dart';
33

4-
// This SharedValue can be shared from any number of widgets.
5-
final counter = SharedValue(
4+
// This global SharedValue can be shared across the entire app
5+
final SharedValue<int> counter = SharedValue(
66
value: 0, // initial value
77
key: "counter", // disk storage key for shared_preferences
8+
autosave: true, // autosave to shared prefs when value changes
89
);
910

10-
void main() {
11-
runApp(SharedValue.wrapApp(MyApp()));
11+
Future<void> main() async {
12+
runApp(SharedValue.wrapApp(MyApp())); // don't forget this!
1213
}
1314

1415
class MyApp extends StatelessWidget {
@@ -39,7 +40,7 @@ class _MyHomePageState extends State<MyHomePage> {
3940
@override
4041
Widget build(BuildContext context) {
4142
// The .of(context) bit makes this widget rebuild everytime counter is changed
42-
var counterValue = counter.of(context);
43+
int counterValue = counter.of(context);
4344

4445
return Scaffold(
4546
appBar: AppBar(
@@ -71,16 +72,11 @@ class _MyHomePageState extends State<MyHomePage> {
7172
void initState() {
7273
super.initState();
7374

74-
// Load the previously stored value of counter to disk using shared_preferences
75-
counter.load();
75+
counter.load(); // load previous value from shared prefs
7676
}
7777

7878
Future<void> _incrementCounter() async {
79-
setState(() {});
8079
// update counter value and rebuild all widgets using that value
8180
counter.update((value) => value + 1);
82-
83-
// Save the internal value of counter to disk using shared_preferences
84-
await counter.save();
8581
}
8682
}

example/pubspec.lock

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,42 +7,42 @@ packages:
77
name: async
88
url: "https://pub.dartlang.org"
99
source: hosted
10-
version: "2.4.2"
10+
version: "2.5.0-nullsafety.1"
1111
boolean_selector:
1212
dependency: transitive
1313
description:
1414
name: boolean_selector
1515
url: "https://pub.dartlang.org"
1616
source: hosted
17-
version: "2.0.0"
17+
version: "2.1.0-nullsafety.1"
1818
characters:
1919
dependency: transitive
2020
description:
2121
name: characters
2222
url: "https://pub.dartlang.org"
2323
source: hosted
24-
version: "1.0.0"
24+
version: "1.1.0-nullsafety.3"
2525
charcode:
2626
dependency: transitive
2727
description:
2828
name: charcode
2929
url: "https://pub.dartlang.org"
3030
source: hosted
31-
version: "1.1.3"
31+
version: "1.2.0-nullsafety.1"
3232
clock:
3333
dependency: transitive
3434
description:
3535
name: clock
3636
url: "https://pub.dartlang.org"
3737
source: hosted
38-
version: "1.0.1"
38+
version: "1.1.0-nullsafety.1"
3939
collection:
4040
dependency: transitive
4141
description:
4242
name: collection
4343
url: "https://pub.dartlang.org"
4444
source: hosted
45-
version: "1.14.13"
45+
version: "1.15.0-nullsafety.3"
4646
cupertino_icons:
4747
dependency: "direct main"
4848
description:
@@ -56,7 +56,7 @@ packages:
5656
name: fake_async
5757
url: "https://pub.dartlang.org"
5858
source: hosted
59-
version: "1.1.0"
59+
version: "1.2.0-nullsafety.1"
6060
flutter:
6161
dependency: "direct main"
6262
description: flutter
@@ -78,21 +78,21 @@ packages:
7878
name: matcher
7979
url: "https://pub.dartlang.org"
8080
source: hosted
81-
version: "0.12.8"
81+
version: "0.12.10-nullsafety.1"
8282
meta:
8383
dependency: transitive
8484
description:
8585
name: meta
8686
url: "https://pub.dartlang.org"
8787
source: hosted
88-
version: "1.1.8"
88+
version: "1.3.0-nullsafety.3"
8989
path:
9090
dependency: transitive
9191
description:
9292
name: path
9393
url: "https://pub.dartlang.org"
9494
source: hosted
95-
version: "1.7.0"
95+
version: "1.8.0-nullsafety.1"
9696
shared_preferences:
9797
dependency: transitive
9898
description:
@@ -127,7 +127,7 @@ packages:
127127
path: ".."
128128
relative: true
129129
source: path
130-
version: "0.1.5"
130+
version: "0.2.0"
131131
sky_engine:
132132
dependency: transitive
133133
description: flutter
@@ -139,56 +139,56 @@ packages:
139139
name: source_span
140140
url: "https://pub.dartlang.org"
141141
source: hosted
142-
version: "1.7.0"
142+
version: "1.8.0-nullsafety.2"
143143
stack_trace:
144144
dependency: transitive
145145
description:
146146
name: stack_trace
147147
url: "https://pub.dartlang.org"
148148
source: hosted
149-
version: "1.9.5"
149+
version: "1.10.0-nullsafety.1"
150150
stream_channel:
151151
dependency: transitive
152152
description:
153153
name: stream_channel
154154
url: "https://pub.dartlang.org"
155155
source: hosted
156-
version: "2.0.0"
156+
version: "2.1.0-nullsafety.1"
157157
string_scanner:
158158
dependency: transitive
159159
description:
160160
name: string_scanner
161161
url: "https://pub.dartlang.org"
162162
source: hosted
163-
version: "1.0.5"
163+
version: "1.1.0-nullsafety.1"
164164
term_glyph:
165165
dependency: transitive
166166
description:
167167
name: term_glyph
168168
url: "https://pub.dartlang.org"
169169
source: hosted
170-
version: "1.1.0"
170+
version: "1.2.0-nullsafety.1"
171171
test_api:
172172
dependency: transitive
173173
description:
174174
name: test_api
175175
url: "https://pub.dartlang.org"
176176
source: hosted
177-
version: "0.2.17"
177+
version: "0.2.19-nullsafety.2"
178178
typed_data:
179179
dependency: transitive
180180
description:
181181
name: typed_data
182182
url: "https://pub.dartlang.org"
183183
source: hosted
184-
version: "1.2.0"
184+
version: "1.3.0-nullsafety.3"
185185
vector_math:
186186
dependency: transitive
187187
description:
188188
name: vector_math
189189
url: "https://pub.dartlang.org"
190190
source: hosted
191-
version: "2.0.8"
191+
version: "2.1.0-nullsafety.3"
192192
sdks:
193-
dart: ">=2.9.0-14.0.dev <3.0.0"
193+
dart: ">=2.10.0-110 <2.11.0"
194194
flutter: ">=1.12.13+hotfix.4 <2.0.0"

lib/manager_widget.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,14 @@ class StateManagerWidget extends StatefulWidget {
2323

2424
class StateManagerWidgetState extends State<StateManagerWidget> {
2525
void rebuild() {
26+
if (!mounted) return;
2627
try {
2728
setState(() {});
28-
} catch (_) {}
29+
} catch (_) {
30+
WidgetsBinding.instance.addPostFrameCallback((_) {
31+
setState(() {});
32+
});
33+
}
2934
}
3035

3136
@override

lib/shared_value.dart

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,22 @@ class SharedValue<T> {
3232
/// The key to use for storing this value in shared preferences.
3333
final String key;
3434

35-
SharedValue({this.key, T value}) {
35+
/// automatically save to shared preferences when the value changes
36+
final bool autosave;
37+
38+
SharedValue({this.key, T value, this.autosave = false}) {
3639
_value = value;
3740
_update(rebuild: false);
3841
}
3942

43+
/// Alias for [value]
44+
T get $ => value;
45+
46+
/// Alias for [value]
47+
set $(T newValue) {
48+
value = newValue;
49+
}
50+
4051
/// The value held by this state.
4152
T get value => _value;
4253

@@ -110,12 +121,17 @@ class SharedValue<T> {
110121

111122
// add value to stream
112123
_controller?.add(value);
124+
125+
if (autosave) {
126+
save();
127+
}
113128
}
114129

115130
/// Try to load the value stored at [key] in shared preferences.
116131
/// If no value is found, return immediately.
117132
/// Else, udpdate [value] and rebuild dependent widgets if it changed.
118133
Future<void> load() async {
134+
assert(key != null);
119135
var pref = await SharedPreferences.getInstance();
120136
var str = pref.getString(key);
121137
if (str == null) return;
@@ -124,16 +140,17 @@ class SharedValue<T> {
124140

125141
/// Store the current [value] at [key] in shared preferences.
126142
Future<void> save() async {
143+
assert(key != null);
127144
var pref = await SharedPreferences.getInstance();
128145
await pref.setString(key, serialize(_value));
129146
}
130147

131-
/// serialize [obj] of type [T].
148+
/// serialize [obj] of type [T] for shared preferences.
132149
String serialize(T obj) {
133150
return jsonEncode(obj);
134151
}
135152

136-
/// desrialize [str] to an obj of type [T].
153+
/// desrialize [str] to an obj of type [T] for shared preferences.
137154
T deserialize(String str) {
138155
return jsonDecode(str) as T;
139156
}

0 commit comments

Comments
 (0)