Last active
January 8, 2020 17:49
-
-
Save rrousselGit/a19a34d624d455caf7767539e712b00d to your computer and use it in GitHub Desktop.
InheritedNotificationListener with subclass and event blubbling
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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