Commit e361c0b0 authored by Adam Barth's avatar Adam Barth

Inherited widgets should work across reactivations

Previously we updated only the reactivated element's inherited widgets. Now we
update all the inherited widgets for the whole subtree that's being
reactivated. We need to visit the whole subtree anyway, so there isn't much of
a loss.

Fixes #2733
Fixes #2438
Fixes #1701
parent 7940e26b
......@@ -911,10 +911,9 @@ abstract class Element implements BuildContext {
void activate(Element parent, dynamic newSlot) {
assert(_debugLifecycleState == _ElementLifecycle.inactive);
_reactivate();
_parent = parent;
_reactivate();
_updateDepth();
_updateInheritance();
attachRenderObject(newSlot);
assert(_debugLifecycleState == _ElementLifecycle.active);
}
......@@ -925,6 +924,7 @@ abstract class Element implements BuildContext {
assert(depth != null);
assert(!_active);
_active = true;
_updateInheritance();
assert(() { _debugLifecycleState = _ElementLifecycle.active; return true; });
visitChildren((Element child) => child._reactivate());
}
......@@ -939,6 +939,7 @@ abstract class Element implements BuildContext {
dependency._dependents.remove(this);
_dependencies.clear();
}
_inheritedWidgets = null;
_active = false;
assert(() { _debugLifecycleState = _ElementLifecycle.inactive; return true; });
}
......@@ -981,6 +982,7 @@ abstract class Element implements BuildContext {
}
void _updateInheritance() {
assert(_active);
_inheritedWidgets = _parent?._inheritedWidgets;
}
......@@ -1545,6 +1547,7 @@ class InheritedElement extends _ProxyElement {
@override
void _updateInheritance() {
assert(_active);
final Map<Type, InheritedElement> incomingWidgets = _parent?._inheritedWidgets;
if (incomingWidgets != null)
_inheritedWidgets = new Map<Type, InheritedElement>.from(incomingWidgets);
......
// Copyright 2015 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 'package:flutter_test/flutter_test.dart';
import 'package:flutter/material.dart';
import 'package:test/test.dart';
class TestInherited extends InheritedWidget {
TestInherited({ Key key, Widget child, this.shouldNotify: true })
: super(key: key, child: child);
final bool shouldNotify;
@override
bool updateShouldNotify(InheritedWidget oldWidget) {
return shouldNotify;
}
}
void main() {
test('Inherited notifies dependents', () {
testWidgets((WidgetTester tester) {
List<TestInherited> log = <TestInherited>[];
Builder builder = new Builder(
builder: (BuildContext context) {
log.add(context.inheritFromWidgetOfExactType(TestInherited));
return new Container();
}
);
TestInherited first = new TestInherited(child: builder);
tester.pumpWidget(first);
expect(log, equals([first]));
TestInherited second = new TestInherited(child: builder, shouldNotify: false);
tester.pumpWidget(second);
expect(log, equals([first]));
TestInherited third = new TestInherited(child: builder, shouldNotify: true);
tester.pumpWidget(third);
expect(log, equals([first, third]));
});
});
test('Update inherited when reparenting state', () {
testWidgets((WidgetTester tester) {
GlobalKey globalKey = new GlobalKey();
List<TestInherited> log = <TestInherited>[];
TestInherited build() {
return new TestInherited(
key: new UniqueKey(),
child: new Container(
key: globalKey,
child: new Builder(
builder: (BuildContext context) {
log.add(context.inheritFromWidgetOfExactType(TestInherited));
return new Container();
}
)
)
);
}
TestInherited first = build();
tester.pumpWidget(first);
expect(log, equals([first]));
TestInherited second = build();
tester.pumpWidget(second);
expect(log, equals([first, second]));
});
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment