Skip to content

Instantly share code, notes, and snippets.

@rrousselGit
Last active January 8, 2020 17:49
Show Gist options
  • Save rrousselGit/a19a34d624d455caf7767539e712b00d to your computer and use it in GitHub Desktop.
Save rrousselGit/a19a34d624d455caf7767539e712b00d to your computer and use it in GitHub Desktop.
InheritedNotificationListener with subclass and event blubbling
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class _InheritedNotificationListener extends InheritedWidget {
_InheritedNotificationListener({
Key key,
this.maybeNotify,
Widget child,
}) : super(key: key, child: child);
final bool Function(Object value) maybeNotify;
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return false;
}
}
class InheritedNotificationListener<T> extends StatelessWidget {
const InheritedNotificationListener({
Key key,
this.onNotification,
this.child,
}) : super(key: key);
static void dispatch(BuildContext context, Object value) {
bool shouldStop = false;
while (!shouldStop) {
final element = context.ancestorInheritedElementForWidgetOfExactType(
_InheritedNotificationListener);
final widget = element?.widget as _InheritedNotificationListener;
shouldStop = widget?.maybeNotify(value) ?? true;
element?.visitAncestorElements((e) {
context = e;
return false;
});
}
}
final Widget child;
final bool Function(T value) onNotification;
@override
Widget build(BuildContext context) {
return _InheritedNotificationListener(
maybeNotify: _maybeNotify,
child: child,
);
}
bool _maybeNotify(Object value) {
if (value is T) {
return onNotification(value);
}
return false;
}
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return InheritedNotificationListener(
onNotification: (int value) {
print('received int $value');
return false; // bubble
},
child: InheritedNotificationListener(
onNotification: (num value) {
print('received num $value');
return false; // bubble
},
child: MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
),
),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: RaisedButton(
onPressed: () {
InheritedNotificationListener.dispatch(context, 42);
},
child: Text('dispatch'),
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment