Skip to content

Commit 0bef9dd

Browse files
committed
store [nfc]: Add and use PerAccountStoreAwareStateMixin
1 parent 38ed6c8 commit 0bef9dd

File tree

2 files changed

+39
-10
lines changed

2 files changed

+39
-10
lines changed

lib/widgets/message_list.dart

+3-10
Original file line numberDiff line numberDiff line change
@@ -107,20 +107,13 @@ class MessageList extends StatefulWidget {
107107
State<StatefulWidget> createState() => _MessageListState();
108108
}
109109

110-
class _MessageListState extends State<MessageList> {
110+
class _MessageListState extends State<MessageList> with PerAccountStoreAwareStateMixin<MessageList> {
111111
MessageListView? model;
112112

113113
@override
114-
void didChangeDependencies() {
115-
super.didChangeDependencies();
116-
final store = PerAccountStoreWidget.of(context);
117-
if (model != null && model!.store == store) {
118-
// We already have a model, and it's for the right store.
119-
return;
120-
}
121-
// Otherwise, set up the model. Dispose of any old model.
114+
void onNewStore() {
122115
model?.dispose();
123-
_initModel(store);
116+
_initModel(PerAccountStoreWidget.of(context));
124117
}
125118

126119
@override

lib/widgets/store.dart

+36
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,9 @@ class PerAccountStoreWidget extends StatefulWidget {
140140
/// * [GlobalStoreWidget.of], for the app's data beyond that of a
141141
/// particular account.
142142
/// * [InheritedNotifier], which provides the "dependency" mechanism.
143+
// TODO(#185): Explain in dartdoc that the returned [PerAccountStore] might
144+
// differ from one call to the next, and to handle that with
145+
// [PerAccountStoreAwareStateMixin].
143146
static PerAccountStore of(BuildContext context) {
144147
final widget = context.dependOnInheritedWidgetOfExactType<_PerAccountStoreInheritedWidget>();
145148
assert(widget != null, 'No PerAccountStoreWidget ancestor');
@@ -246,3 +249,36 @@ class LoadingPage extends StatelessWidget {
246249
return const Center(child: CircularProgressIndicator());
247250
}
248251
}
252+
253+
/// A [State] that uses the ambient [PerAccountStore].
254+
///
255+
/// The ambient [PerAccountStore] can be replaced in some circumstances,
256+
/// such as when an event queue expires. See [PerAccountStoreWidget.of].
257+
/// When that happens, stateful widgets should
258+
/// - remove listeners on the old [PerAccountStore], and
259+
/// - add listeners on the new one.
260+
/// Use this mixin, overriding [onNewStore], to do that concisely.
261+
// TODO(#185): Until #185, I think [PerAccountStoreWidget.of] never actually
262+
// returns a different [PerAccountStore] from one call to the next.
263+
// But it will, and when it does, we want our [StatefulWidgets] to handle it.
264+
mixin PerAccountStoreAwareStateMixin<T extends StatefulWidget> on State<T> {
265+
PerAccountStore? _store;
266+
267+
/// Called in the first [State.didChangeDependencies] call, and afterward
268+
/// when [PerAccountStoreWidget.of] returns a different store than last time.
269+
///
270+
/// In this, remove any listeners on the old store
271+
/// and add them on the new store.
272+
void onNewStore();
273+
274+
@override
275+
void didChangeDependencies() {
276+
super.didChangeDependencies();
277+
278+
final storeNow = PerAccountStoreWidget.of(context);
279+
if (_store != storeNow) {
280+
onNewStore();
281+
}
282+
_store = storeNow;
283+
}
284+
}

0 commit comments

Comments
 (0)