Last active
April 27, 2016 22:41
-
-
Save abarth/cad90f75fd892effdc2836cecfdf5647 to your computer and use it in GitHub Desktop.
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 2016 The Chromium Authors. All rights reserved. | |
// Use of this source code is governed by a BSD-style license that can be | |
// found in the LICENSE file. | |
import 'dart:async'; | |
import 'package:flutter/widgets.dart'; | |
/// ```dart | |
/// class FooModel extends Listenable { | |
/// String get bar => _bar; | |
/// String _bar; | |
/// void set bar(String value) { | |
/// if (_bar == value) | |
/// return; | |
/// _bar = value; | |
/// notifyListeners(); | |
/// } | |
/// } | |
/// ``` | |
class Listenable { | |
final Set<VoidCallback> _listeners = new Set<VoidCallback>(); | |
void addListener(VoidCallback listener) { | |
assert(!_listeners.contains(listener)); | |
_listeners.add(listener); | |
} | |
void removeListener(VoidCallback listener) { | |
assert(_listeners.contains(listener)); | |
_listeners.remove(listener); | |
} | |
void notifyListeners() { | |
if (_notificationScheduled) | |
return; | |
_notificationScheduled = true; | |
scheduleMicrotask(_dispatchNotifications); | |
} | |
bool _notificationScheduled = false; | |
void _dispatchNotifications() { | |
_notificationScheduled = false; | |
List<VoidCallback> localListeners = new List<VoidCallback>.from(_listeners); | |
for (VoidCallback listener in localListeners) | |
listener(); | |
} | |
} | |
/// ```dart | |
/// Widget build(BuildContext context) { | |
/// FooModel foo = const ModelProvider<FooModel>().of(context); | |
/// return new Text(foo.bar); | |
/// } | |
/// ``` | |
class ModelProvider<T extends Listenable> extends InheritedWidget { | |
const ModelProvider({ Key key, Widget child, this.model }) : super(key: key, child: child); | |
T of(BuildContext context) { | |
ModelProvider<T> found = context.inheritFromWidgetOfExactType(runtimeType); | |
return found?.model; | |
} | |
final T model; | |
@override | |
bool updateShouldNotify(ModelProvider<T> oldWidget) => model != oldWidget.model; | |
@override | |
_ModelProviderElement createElement() => new _ModelProviderElement(this); | |
} | |
class _ModelProviderElement<T extends Listenable> extends InheritedElement { | |
_ModelProviderElement(ModelProvider<T> widget) : super(widget); | |
@override | |
ModelProvider<T> get widget => super.widget; | |
@override | |
void mount(Element parent, dynamic newSlot) { | |
super.mount(parent, newSlot); | |
widget.model.addListener(dispatchDependenciesChanged); | |
} | |
@override | |
void update(ModelProvider<T> newWidget) { | |
final ModelProvider<T> oldWidget = widget; | |
super.update(newWidget); | |
if (oldWidget.model != newWidget.model) { | |
oldWidget.model.removeListener(dispatchDependenciesChanged); | |
newWidget.model.addListener(dispatchDependenciesChanged); | |
} | |
} | |
@override | |
void unmount() { | |
widget.model.removeListener(dispatchDependenciesChanged); | |
super.unmount(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment