Unverified Commit b007a81a authored by Alexandre Ardhuin's avatar Alexandre Ardhuin Committed by GitHub

Reland "Nnbd widgets" (#65528)

* Reland "Nnbd widgets (#64672)"

This reverts commit 127e6790.

* remove non-nullable enforcement on AsyncSnapshot

* make data param non-nullable for AsyncSnapshot.withData

* make some Text params non-nullable
parent 96ca0e27
......@@ -645,7 +645,7 @@ class CupertinoTextField extends StatefulWidget {
}
}
class _CupertinoTextFieldState extends State<CupertinoTextField> with RestorationMixin, AutomaticKeepAliveClientMixin implements TextSelectionGestureDetectorBuilderDelegate {
class _CupertinoTextFieldState extends State<CupertinoTextField> with RestorationMixin, AutomaticKeepAliveClientMixin<CupertinoTextField> implements TextSelectionGestureDetectorBuilderDelegate {
final GlobalKey _clearGlobalKey = GlobalKey();
RestorableTextEditingController _controller;
......
......@@ -196,28 +196,11 @@ abstract class RenderSliverFixedExtentBoxAdaptor extends RenderSliverMultiBoxAda
if (firstChild == null) {
if (!addInitialChild(index: firstIndex, layoutOffset: indexToLayoutOffset(itemExtent, firstIndex))) {
// There are either no children, or we are past the end of all our children.
// If it is the latter, we will need to find the first available child.
double max;
if (childManager.childCount != null) {
max = computeMaxScrollOffset(constraints, itemExtent);
// TODO(ianh): null-aware flow analysis flags the next two
// branches as entirely dead code, and it's hard to argue with
// its logic.
} else if (firstIndex <= 0) { // ignore: dead_code
if (firstIndex <= 0) {
max = 0.0;
} else {
// We will have to find it manually.
int possibleFirstIndex = firstIndex - 1;
while (
possibleFirstIndex > 0 &&
!addInitialChild(
index: possibleFirstIndex,
layoutOffset: indexToLayoutOffset(itemExtent, possibleFirstIndex),
)
) {
possibleFirstIndex -= 1;
}
max = (possibleFirstIndex + 1) * itemExtent;
max = computeMaxScrollOffset(constraints, itemExtent);
}
geometry = SliverGeometry(
scrollExtent: max,
......
......@@ -94,6 +94,9 @@ abstract class ViewportOffset extends ChangeNotifier {
/// the value changes due to [correctBy]).
double get pixels;
/// Whether the [pixels] property is available.
bool get hasPixels;
/// Called when the viewport's extents are established.
///
/// The argument is the dimension of the [RenderViewport] in the main axis
......@@ -245,7 +248,9 @@ abstract class ViewportOffset extends ChangeNotifier {
/// `super.debugFillDescription(description)`.
@mustCallSuper
void debugFillDescription(List<String> description) {
description.add('offset: ${pixels.toStringAsFixed(1)}');
if (hasPixels) {
description.add('offset: ${pixels.toStringAsFixed(1)}');
}
}
}
......@@ -258,6 +263,9 @@ class _FixedViewportOffset extends ViewportOffset {
@override
double get pixels => _pixels;
@override
bool get hasPixels => true;
@override
bool applyViewportDimension(double viewportDimension) => true;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/rendering.dart';
import 'animated_size.dart';
......@@ -120,15 +118,15 @@ class AnimatedCrossFade extends StatefulWidget {
///
/// All the arguments other than [key] must be non-null.
const AnimatedCrossFade({
Key key,
@required this.firstChild,
@required this.secondChild,
Key? key,
required this.firstChild,
required this.secondChild,
this.firstCurve = Curves.linear,
this.secondCurve = Curves.linear,
this.sizeCurve = Curves.linear,
this.alignment = Alignment.topCenter,
@required this.crossFadeState,
@required this.duration,
required this.crossFadeState,
required this.duration,
this.reverseDuration,
this.layoutBuilder = defaultLayoutBuilder,
}) : assert(firstChild != null),
......@@ -163,7 +161,7 @@ class AnimatedCrossFade extends StatefulWidget {
/// The duration of the whole orchestrated animation when running in reverse.
///
/// If not supplied, this defaults to [duration].
final Duration reverseDuration;
final Duration? reverseDuration;
/// The fade curve of the first child.
///
......@@ -249,9 +247,9 @@ class AnimatedCrossFade extends StatefulWidget {
}
class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProviderStateMixin {
AnimationController _controller;
Animation<double> _firstAnimation;
Animation<double> _secondAnimation;
AnimationController? _controller;
late Animation<double> _firstAnimation;
late Animation<double> _secondAnimation;
@override
void initState() {
......@@ -262,10 +260,10 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
vsync: this,
);
if (widget.crossFadeState == CrossFadeState.showSecond)
_controller.value = 1.0;
_controller!.value = 1.0;
_firstAnimation = _initAnimation(widget.firstCurve, true);
_secondAnimation = _initAnimation(widget.secondCurve, false);
_controller.addStatusListener((AnimationStatus status) {
_controller!.addStatusListener((AnimationStatus status) {
setState(() {
// Trigger a rebuild because it depends on _isTransitioning, which
// changes its value together with animation status.
......@@ -274,7 +272,7 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
}
Animation<double> _initAnimation(Curve curve, bool inverted) {
Animation<double> result = _controller.drive(CurveTween(curve: curve));
Animation<double> result = _controller!.drive(CurveTween(curve: curve));
if (inverted)
result = result.drive(Tween<double>(begin: 1.0, end: 0.0));
return result;
......@@ -282,7 +280,7 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
@override
void dispose() {
_controller.dispose();
_controller!.dispose();
super.dispose();
}
......@@ -290,9 +288,9 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
void didUpdateWidget(AnimatedCrossFade oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.duration != oldWidget.duration)
_controller.duration = widget.duration;
_controller!.duration = widget.duration;
if (widget.reverseDuration != oldWidget.reverseDuration)
_controller.reverseDuration = widget.reverseDuration;
_controller!.reverseDuration = widget.reverseDuration;
if (widget.firstCurve != oldWidget.firstCurve)
_firstAnimation = _initAnimation(widget.firstCurve, true);
if (widget.secondCurve != oldWidget.secondCurve)
......@@ -300,24 +298,24 @@ class _AnimatedCrossFadeState extends State<AnimatedCrossFade> with TickerProvid
if (widget.crossFadeState != oldWidget.crossFadeState) {
switch (widget.crossFadeState) {
case CrossFadeState.showFirst:
_controller.reverse();
_controller!.reverse();
break;
case CrossFadeState.showSecond:
_controller.forward();
_controller!.forward();
break;
}
}
}
/// Whether we're in the middle of cross-fading this frame.
bool get _isTransitioning => _controller.status == AnimationStatus.forward || _controller.status == AnimationStatus.reverse;
bool get _isTransitioning => _controller!.status == AnimationStatus.forward || _controller!.status == AnimationStatus.reverse;
@override
Widget build(BuildContext context) {
const Key kFirstChildKey = ValueKey<CrossFadeState>(CrossFadeState.showFirst);
const Key kSecondChildKey = ValueKey<CrossFadeState>(CrossFadeState.showSecond);
final bool transitioningForwards = _controller.status == AnimationStatus.completed ||
_controller.status == AnimationStatus.forward;
final bool transitioningForwards = _controller!.status == AnimationStatus.completed ||
_controller!.status == AnimationStatus.forward;
Key topKey;
Widget topChild;
Animation<double> topAnimation;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart';
......@@ -32,8 +30,8 @@ class _ActiveItem implements Comparable<_ActiveItem> {
: controller = null,
removedItemBuilder = null;
final AnimationController controller;
final AnimatedListRemovedItemBuilder removedItemBuilder;
final AnimationController? controller;
final AnimatedListRemovedItemBuilder? removedItemBuilder;
int itemIndex;
@override
......@@ -271,8 +269,8 @@ class AnimatedList extends StatefulWidget {
/// Creates a scrolling container that animates items when they are inserted
/// or removed.
const AnimatedList({
Key key,
@required this.itemBuilder,
Key? key,
required this.itemBuilder,
this.initialItemCount = 0,
this.scrollDirection = Axis.vertical,
this.reverse = false,
......@@ -339,7 +337,7 @@ class AnimatedList extends StatefulWidget {
/// [ScrollController.keepScrollOffset]). It can be used to read the current
/// scroll position (see [ScrollController.offset]), or change it (see
/// [ScrollController.animateTo]).
final ScrollController controller;
final ScrollController? controller;
/// Whether this is the primary scroll view associated with the parent
/// [PrimaryScrollController].
......@@ -349,7 +347,7 @@ class AnimatedList extends StatefulWidget {
///
/// Defaults to true when [scrollDirection] is [Axis.vertical] and
/// [controller] is null.
final bool primary;
final bool? primary;
/// How the scroll view should respond to user input.
///
......@@ -357,7 +355,7 @@ class AnimatedList extends StatefulWidget {
/// user stops dragging the scroll view.
///
/// Defaults to matching platform conventions.
final ScrollPhysics physics;
final ScrollPhysics? physics;
/// Whether the extent of the scroll view in the [scrollDirection] should be
/// determined by the contents being viewed.
......@@ -376,7 +374,7 @@ class AnimatedList extends StatefulWidget {
final bool shrinkWrap;
/// The amount of space by which to inset the children.
final EdgeInsetsGeometry padding;
final EdgeInsetsGeometry? padding;
/// The state from the closest instance of this class that encloses the given
/// context.
......@@ -387,10 +385,10 @@ class AnimatedList extends StatefulWidget {
/// ```dart
/// AnimatedListState animatedList = AnimatedList.of(context);
/// ```
static AnimatedListState of(BuildContext context, { bool nullOk = false }) {
static AnimatedListState? of(BuildContext context, { bool nullOk = false }) {
assert(context != null);
assert(nullOk != null);
final AnimatedListState result = context.findAncestorStateOfType<AnimatedListState>();
final AnimatedListState? result = context.findAncestorStateOfType<AnimatedListState>();
if (nullOk || result != null)
return result;
throw FlutterError.fromParts(<DiagnosticsNode>[
......@@ -444,7 +442,7 @@ class AnimatedListState extends State<AnimatedList> with TickerProviderStateMixi
/// it increases the length of the list by one and shifts all items at or
/// after [index] towards the end of the list.
void insertItem(int index, { Duration duration = _kDuration }) {
_sliverAnimatedListKey.currentState.insertItem(index, duration: duration);
_sliverAnimatedListKey.currentState!.insertItem(index, duration: duration);
}
/// Remove the item at [index] and start an animation that will be passed
......@@ -459,7 +457,7 @@ class AnimatedListState extends State<AnimatedList> with TickerProviderStateMixi
/// it decreases the length of the list by one and shifts all items at or
/// before [index] towards the beginning of the list.
void removeItem(int index, AnimatedListRemovedItemBuilder builder, { Duration duration = _kDuration }) {
_sliverAnimatedListKey.currentState.removeItem(index, builder, duration: duration);
_sliverAnimatedListKey.currentState!.removeItem(index, builder, duration: duration);
}
@override
......@@ -736,8 +734,8 @@ class AnimatedListState extends State<AnimatedList> with TickerProviderStateMixi
class SliverAnimatedList extends StatefulWidget {
/// Creates a sliver that animates items when they are inserted or removed.
const SliverAnimatedList({
Key key,
@required this.itemBuilder,
Key? key,
required this.itemBuilder,
this.initialItemCount = 0,
}) : assert(itemBuilder != null),
assert(initialItemCount != null && initialItemCount >= 0),
......@@ -773,10 +771,10 @@ class SliverAnimatedList extends StatefulWidget {
/// ```dart
/// SliverAnimatedListState animatedList = SliverAnimatedList.of(context);
/// ```
static SliverAnimatedListState of(BuildContext context, {bool nullOk = false}) {
static SliverAnimatedListState? of(BuildContext context, {bool nullOk = false}) {
assert(context != null);
assert(nullOk != null);
final SliverAnimatedListState result = context.findAncestorStateOfType<SliverAnimatedListState>();
final SliverAnimatedListState? result = context.findAncestorStateOfType<SliverAnimatedListState>();
if (nullOk || result != null)
return result;
throw FlutterError(
......@@ -831,17 +829,17 @@ class SliverAnimatedListState extends State<SliverAnimatedList> with TickerProvi
@override
void dispose() {
for (final _ActiveItem item in _incomingItems.followedBy(_outgoingItems)) {
item.controller.dispose();
item.controller!.dispose();
}
super.dispose();
}
_ActiveItem _removeActiveItemAt(List<_ActiveItem> items, int itemIndex) {
_ActiveItem? _removeActiveItemAt(List<_ActiveItem> items, int itemIndex) {
final int i = binarySearch(items, _ActiveItem.index(itemIndex));
return i == -1 ? null : items.removeAt(i);
}
_ActiveItem _activeItemAt(List<_ActiveItem> items, int itemIndex) {
_ActiveItem? _activeItemAt(List<_ActiveItem> items, int itemIndex) {
final int i = binarySearch(items, _ActiveItem.index(itemIndex));
return i == -1 ? null : items[i];
}
......@@ -919,7 +917,7 @@ class SliverAnimatedListState extends State<SliverAnimatedList> with TickerProvi
});
controller.forward().then<void>((_) {
_removeActiveItemAt(_incomingItems, incomingItem.itemIndex).controller.dispose();
_removeActiveItemAt(_incomingItems, incomingItem.itemIndex)!.controller!.dispose();
});
}
......@@ -943,7 +941,7 @@ class SliverAnimatedListState extends State<SliverAnimatedList> with TickerProvi
assert(itemIndex >= 0 && itemIndex < _itemsCount);
assert(_activeItemAt(_outgoingItems, itemIndex) == null);
final _ActiveItem incomingItem = _removeActiveItemAt(_incomingItems, itemIndex);
final _ActiveItem? incomingItem = _removeActiveItemAt(_incomingItems, itemIndex);
final AnimationController controller = incomingItem?.controller
?? AnimationController(duration: duration, value: 1.0, vsync: this);
final _ActiveItem outgoingItem = _ActiveItem.outgoing(controller, itemIndex, builder);
......@@ -954,7 +952,7 @@ class SliverAnimatedListState extends State<SliverAnimatedList> with TickerProvi
});
controller.reverse().then<void>((void value) {
_removeActiveItemAt(_outgoingItems, outgoingItem.itemIndex).controller.dispose();
_removeActiveItemAt(_outgoingItems, outgoingItem.itemIndex)!.controller!.dispose();
// Decrement the incoming and outgoing item indices to account
// for the removal.
......@@ -972,15 +970,15 @@ class SliverAnimatedListState extends State<SliverAnimatedList> with TickerProvi
}
Widget _itemBuilder(BuildContext context, int itemIndex) {
final _ActiveItem outgoingItem = _activeItemAt(_outgoingItems, itemIndex);
final _ActiveItem? outgoingItem = _activeItemAt(_outgoingItems, itemIndex);
if (outgoingItem != null) {
return outgoingItem.removedItemBuilder(
return outgoingItem.removedItemBuilder!(
context,
outgoingItem.controller.view,
outgoingItem.controller!.view,
);
}
final _ActiveItem incomingItem = _activeItemAt(_incomingItems, itemIndex);
final _ActiveItem? incomingItem = _activeItemAt(_incomingItems, itemIndex);
final Animation<double> animation = incomingItem?.controller?.view ?? kAlwaysCompleteAnimation;
return widget.itemBuilder(
context,
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart';
......@@ -56,13 +54,13 @@ class AnimatedSize extends SingleChildRenderObjectWidget {
///
/// The [curve] and [duration] arguments must not be null.
const AnimatedSize({
Key key,
Widget child,
Key? key,
Widget? child,
this.alignment = Alignment.center,
this.curve = Curves.linear,
@required this.duration,
required this.duration,
this.reverseDuration,
@required this.vsync,
required this.vsync,
}) : super(key: key, child: child);
/// The alignment of the child within the parent when the parent is not yet
......@@ -98,7 +96,7 @@ class AnimatedSize extends SingleChildRenderObjectWidget {
/// size when going in reverse.
///
/// If not specified, defaults to [duration].
final Duration reverseDuration;
final Duration? reverseDuration;
/// The [TickerProvider] for this widget.
final TickerProvider vsync;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/animation.dart';
import 'package:flutter/foundation.dart';
......@@ -18,10 +16,10 @@ import 'transitions.dart';
// to expose to the public API (like the controller).
class _ChildEntry {
_ChildEntry({
@required this.controller,
@required this.animation,
@required this.transition,
@required this.widgetChild,
required this.controller,
required this.animation,
required this.transition,
required this.widgetChild,
}) : assert(animation != null),
assert(transition != null),
assert(controller != null);
......@@ -63,7 +61,7 @@ typedef AnimatedSwitcherTransitionBuilder = Widget Function(Widget child, Animat
/// The `previousChildren` list is an unmodifiable list, sorted with the oldest
/// at the beginning and the newest at the end. It does not include the
/// `currentChild`.
typedef AnimatedSwitcherLayoutBuilder = Widget Function(Widget currentChild, List<Widget> previousChildren);
typedef AnimatedSwitcherLayoutBuilder = Widget Function(Widget? currentChild, List<Widget> previousChildren);
/// A widget that by default does a cross-fade between a new widget and the
/// widget previously set on the [AnimatedSwitcher] as a child.
......@@ -148,9 +146,9 @@ class AnimatedSwitcher extends StatefulWidget {
/// The [duration], [transitionBuilder], [layoutBuilder], [switchInCurve], and
/// [switchOutCurve] parameters must not be null.
const AnimatedSwitcher({
Key key,
Key? key,
this.child,
@required this.duration,
required this.duration,
this.reverseDuration,
this.switchInCurve = Curves.linear,
this.switchOutCurve = Curves.linear,
......@@ -174,7 +172,7 @@ class AnimatedSwitcher extends StatefulWidget {
/// (see [Widget.canUpdate]).
///
/// To change the kind of transition used, see [transitionBuilder].
final Widget child;
final Widget? child;
/// The duration of the transition from the old [child] value to the new one.
///
......@@ -191,7 +189,7 @@ class AnimatedSwitcher extends StatefulWidget {
/// transitions already in progress.
///
/// If not set, then the value of [duration] is used by default.
final Duration reverseDuration;
final Duration? reverseDuration;
/// The animation curve to use when transitioning in a new [child].
///
......@@ -274,7 +272,7 @@ class AnimatedSwitcher extends StatefulWidget {
/// each other.
///
/// This is an [AnimatedSwitcherLayoutBuilder] function.
static Widget defaultLayoutBuilder(Widget currentChild, List<Widget> previousChildren) {
static Widget defaultLayoutBuilder(Widget? currentChild, List<Widget> previousChildren) {
return Stack(
children: <Widget>[
...previousChildren,
......@@ -293,9 +291,9 @@ class AnimatedSwitcher extends StatefulWidget {
}
class _AnimatedSwitcherState extends State<AnimatedSwitcher> with TickerProviderStateMixin {
_ChildEntry _currentEntry;
_ChildEntry? _currentEntry;
final Set<_ChildEntry> _outgoingEntries = <_ChildEntry>{};
List<Widget> _outgoingWidgets = const <Widget>[];
List<Widget>? _outgoingWidgets = const <Widget>[];
int _childNumber = 0;
@override
......@@ -313,37 +311,37 @@ class _AnimatedSwitcherState extends State<AnimatedSwitcher> with TickerProvider
if (widget.transitionBuilder != oldWidget.transitionBuilder) {
_outgoingEntries.forEach(_updateTransitionForEntry);
if (_currentEntry != null)
_updateTransitionForEntry(_currentEntry);
_updateTransitionForEntry(_currentEntry!);
_markChildWidgetCacheAsDirty();
}
final bool hasNewChild = widget.child != null;
final bool hasOldChild = _currentEntry != null;
if (hasNewChild != hasOldChild ||
hasNewChild && !Widget.canUpdate(widget.child, _currentEntry.widgetChild)) {
hasNewChild && !Widget.canUpdate(widget.child!, _currentEntry!.widgetChild)) {
// Child has changed, fade current entry out and add new entry.
_childNumber += 1;
_addEntryForNewChild(animate: true);
} else if (_currentEntry != null) {
assert(hasOldChild && hasNewChild);
assert(Widget.canUpdate(widget.child, _currentEntry.widgetChild));
assert(Widget.canUpdate(widget.child!, _currentEntry!.widgetChild));
// Child has been updated. Make sure we update the child widget and
// transition in _currentEntry even though we're not going to start a new
// animation, but keep the key from the previous transition so that we
// update the transition instead of replacing it.
_currentEntry.widgetChild = widget.child;
_updateTransitionForEntry(_currentEntry); // uses entry.widgetChild
_currentEntry!.widgetChild = widget.child!;
_updateTransitionForEntry(_currentEntry!); // uses entry.widgetChild
_markChildWidgetCacheAsDirty();
}
}
void _addEntryForNewChild({ @required bool animate }) {
void _addEntryForNewChild({ required bool animate }) {
assert(animate || _currentEntry == null);
if (_currentEntry != null) {
assert(animate);
assert(!_outgoingEntries.contains(_currentEntry));
_outgoingEntries.add(_currentEntry);
_currentEntry.controller.reverse();
_outgoingEntries.add(_currentEntry!);
_currentEntry!.controller.reverse();
_markChildWidgetCacheAsDirty();
_currentEntry = null;
}
......@@ -360,7 +358,7 @@ class _AnimatedSwitcherState extends State<AnimatedSwitcher> with TickerProvider
reverseCurve: widget.switchOutCurve,
);
_currentEntry = _newEntry(
child: widget.child,
child: widget.child!,
controller: controller,
animation: animation,
builder: widget.transitionBuilder,
......@@ -374,10 +372,10 @@ class _AnimatedSwitcherState extends State<AnimatedSwitcher> with TickerProvider
}
_ChildEntry _newEntry({
@required Widget child,
@required AnimatedSwitcherTransitionBuilder builder,
@required AnimationController controller,
@required Animation<double> animation,
required Widget child,
required AnimatedSwitcherTransitionBuilder builder,
required AnimationController controller,
required Animation<double> animation,
}) {
final _ChildEntry entry = _ChildEntry(
widgetChild: child,
......@@ -414,14 +412,14 @@ class _AnimatedSwitcherState extends State<AnimatedSwitcher> with TickerProvider
_outgoingWidgets ??= List<Widget>.unmodifiable(
_outgoingEntries.map<Widget>((_ChildEntry entry) => entry.transition),
);
assert(_outgoingEntries.length == _outgoingWidgets.length);
assert(_outgoingEntries.isEmpty || _outgoingEntries.last.transition == _outgoingWidgets.last);
assert(_outgoingEntries.length == _outgoingWidgets!.length);
assert(_outgoingEntries.isEmpty || _outgoingEntries.last.transition == _outgoingWidgets!.last);
}
@override
void dispose() {
if (_currentEntry != null)
_currentEntry.controller.dispose();
_currentEntry!.controller.dispose();
for (final _ChildEntry entry in _outgoingEntries)
entry.controller.dispose();
super.dispose();
......@@ -430,6 +428,6 @@ class _AnimatedSwitcherState extends State<AnimatedSwitcher> with TickerProvider
@override
Widget build(BuildContext context) {
_rebuildOutgoingWidgetsIfNeeded();
return widget.layoutBuilder(_currentEntry?.transition, _outgoingWidgets);
return widget.layoutBuilder(_currentEntry?.transition, _outgoingWidgets!);
}
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
......@@ -15,7 +13,7 @@ import 'framework.dart';
///
/// * [Layer.find], for an example of how this value is retrieved.
/// * [AnnotatedRegionLayer], the layer pushed into the layer tree.
class AnnotatedRegion<T> extends SingleChildRenderObjectWidget {
class AnnotatedRegion<T extends Object> extends SingleChildRenderObjectWidget {
/// Creates a new annotated region to insert [value] into the layer tree.
///
/// Neither [child] nor [value] may be null.
......@@ -23,9 +21,9 @@ class AnnotatedRegion<T> extends SingleChildRenderObjectWidget {
/// [sized] defaults to true and controls whether the annotated region will
/// clip its child.
const AnnotatedRegion({
Key key,
@required Widget child,
@required this.value,
Key? key,
required Widget child,
required this.value,
this.sized = true,
}) : assert(value != null),
assert(child != null),
......
This diff is collapsed.
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
/// Widgets that handle interaction with asynchronous computations.
///
/// Asynchronous computations are represented by [Future]s and [Stream]s.
......@@ -50,13 +48,13 @@ import 'framework.dart';
/// recent interaction is needed for widget building.
abstract class StreamBuilderBase<T, S> extends StatefulWidget {
/// Creates a [StreamBuilderBase] connected to the specified [stream].
const StreamBuilderBase({ Key key, this.stream }) : super(key: key);
const StreamBuilderBase({ Key? key, this.stream }) : super(key: key);
/// The asynchronous computation to which this builder is currently connected,
/// possibly null. When changed, the current summary is updated using
/// [afterDisconnected], if the previous stream was not null, followed by
/// [afterConnected], if the new stream is not null.
final Stream<T> stream;
final Stream<T>? stream;
/// Returns the initial summary of stream interaction, typically representing
/// the fact that no interaction has happened at all.
......@@ -103,8 +101,8 @@ abstract class StreamBuilderBase<T, S> extends StatefulWidget {
/// State for [StreamBuilderBase].
class _StreamBuilderBaseState<T, S> extends State<StreamBuilderBase<T, S>> {
StreamSubscription<T> _subscription;
S _summary;
StreamSubscription<T>? _subscription; // ignore: cancel_subscriptions
late S _summary;
@override
void initState() {
......@@ -136,7 +134,7 @@ class _StreamBuilderBaseState<T, S> extends State<StreamBuilderBase<T, S>> {
void _subscribe() {
if (widget.stream != null) {
_subscription = widget.stream.listen((T data) {
_subscription = widget.stream!.listen((T data) {
setState(() {
_summary = widget.afterData(_summary, data);
});
......@@ -155,7 +153,7 @@ class _StreamBuilderBaseState<T, S> extends State<StreamBuilderBase<T, S>> {
void _unsubscribe() {
if (_subscription != null) {
_subscription.cancel();
_subscription!.cancel();
_subscription = null;
}
}
......@@ -203,6 +201,8 @@ enum ConnectionState {
/// with a [Stream].
/// * [FutureBuilder], which builds itself based on a snapshot from interacting
/// with a [Future].
// TODO(a14n): the type parameter should be <T extends Object> to enforce that retrieved data must not be null.
// But it breaks a lot of code in google3. See https://github.com/flutter/flutter/pull/64672#pullrequestreview-485199027
@immutable
class AsyncSnapshot<T> {
/// Creates an [AsyncSnapshot] with the specified [connectionState],
......@@ -218,7 +218,7 @@ class AsyncSnapshot<T> {
const AsyncSnapshot.waiting() : this._(ConnectionState.waiting, null, null);
/// Creates an [AsyncSnapshot] in the specified [state] and with the specified [data].
const AsyncSnapshot.withData(ConnectionState state, T data) : this._(state, data, null);
const AsyncSnapshot.withData(ConnectionState state, T data): this._(state, data, null);
/// Creates an [AsyncSnapshot] in the specified [state] and with the specified [error].
const AsyncSnapshot.withError(ConnectionState state, Object error) : this._(state, null, error);
......@@ -235,7 +235,7 @@ class AsyncSnapshot<T> {
/// If the asynchronous computation has never returned a value, this may be
/// set to an initial data value specified by the relevant widget. See
/// [FutureBuilder.initialData] and [StreamBuilder.initialData].
final T data;
final T? data;
/// Returns latest data received, failing if there is no data.
///
......@@ -243,9 +243,9 @@ class AsyncSnapshot<T> {
/// nor [hasError].
T get requireData {
if (hasData)
return data;
return data!;
if (hasError)
throw error;
throw error!;
throw StateError('Snapshot has neither data nor error');
}
......@@ -254,7 +254,7 @@ class AsyncSnapshot<T> {
/// If this is non-null, [hasError] will be true.
///
/// If [data] is not null, this will be null.
final Object error;
final Object? error;
/// Returns a snapshot like this one, but in the specified [state].
///
......@@ -467,7 +467,7 @@ typedef AsyncWidgetBuilder<T> = Widget Function(BuildContext context, AsyncSnaps
/// * [StreamBuilderBase], which supports widget building based on a computation
/// that spans all interactions made with the stream.
// TODO(ianh): remove unreachable code above once https://github.com/dart-lang/linter/issues/1139 is fixed
class StreamBuilder<T> extends StreamBuilderBase<T, AsyncSnapshot<T>> {
class StreamBuilder<T extends Object> extends StreamBuilderBase<T, AsyncSnapshot<T>> {
/// Creates a new [StreamBuilder] that builds itself based on the latest
/// snapshot of interaction with the specified [stream] and whose build
/// strategy is given by [builder].
......@@ -476,10 +476,10 @@ class StreamBuilder<T> extends StreamBuilderBase<T, AsyncSnapshot<T>> {
///
/// The [builder] must not be null.
const StreamBuilder({
Key key,
Key? key,
this.initialData,
Stream<T> stream,
@required this.builder,
Stream<T>? stream,
required this.builder,
}) : assert(builder != null),
super(key: key, stream: stream);
......@@ -497,10 +497,12 @@ class StreamBuilder<T> extends StreamBuilderBase<T, AsyncSnapshot<T>> {
/// of whether a value is available on the stream: since streams are
/// asynchronous, no events from the stream can be obtained before the initial
/// build.
final T initialData;
final T? initialData;
@override
AsyncSnapshot<T> initial() => AsyncSnapshot<T>.withData(ConnectionState.none, initialData);
AsyncSnapshot<T> initial() => initialData == null
? AsyncSnapshot<T>.nothing()
: AsyncSnapshot<T>.withData(ConnectionState.none, initialData!);
@override
AsyncSnapshot<T> afterConnected(AsyncSnapshot<T> current) => current.inState(ConnectionState.waiting);
......@@ -662,16 +664,16 @@ class StreamBuilder<T> extends StreamBuilderBase<T, AsyncSnapshot<T>> {
/// ```
/// {@end-tool}
// TODO(ianh): remove unreachable code above once https://github.com/dart-lang/sdk/issues/35520 is fixed
class FutureBuilder<T> extends StatefulWidget {
class FutureBuilder<T extends Object> extends StatefulWidget {
/// Creates a widget that builds itself based on the latest snapshot of
/// interaction with a [Future].
///
/// The [builder] must not be null.
const FutureBuilder({
Key key,
Key? key,
this.future,
this.initialData,
@required this.builder,
required this.builder,
}) : assert(builder != null),
super(key: key);
......@@ -680,7 +682,7 @@ class FutureBuilder<T> extends StatefulWidget {
///
/// If no future has yet completed, including in the case where [future] is
/// null, the data provided to the [builder] will be set to [initialData].
final Future<T> future;
final Future<T>? future;
/// The build strategy currently used by this builder.
///
......@@ -714,24 +716,26 @@ class FutureBuilder<T> extends StatefulWidget {
/// provided to the [builder] will become null, regardless of [initialData].
/// (The error itself will be available in [AsyncSnapshot.error], and
/// [AsyncSnapshot.hasError] will be true.)
final T initialData;
final T? initialData;
@override
State<FutureBuilder<T>> createState() => _FutureBuilderState<T>();
}
/// State for [FutureBuilder].
class _FutureBuilderState<T> extends State<FutureBuilder<T>> {
class _FutureBuilderState<T extends Object> extends State<FutureBuilder<T>> {
/// An object that identifies the currently active callbacks. Used to avoid
/// calling setState from stale callbacks, e.g. after disposal of this state,
/// or after widget reconfiguration to a new Future.
Object _activeCallbackIdentity;
AsyncSnapshot<T> _snapshot;
Object? _activeCallbackIdentity;
late AsyncSnapshot<T> _snapshot;
@override
void initState() {
super.initState();
_snapshot = AsyncSnapshot<T>.withData(ConnectionState.none, widget.initialData);
_snapshot = widget.initialData == null
? AsyncSnapshot<T>.nothing()
: AsyncSnapshot<T>.withData(ConnectionState.none, widget.initialData!);
_subscribe();
}
......@@ -760,7 +764,7 @@ class _FutureBuilderState<T> extends State<FutureBuilder<T>> {
if (widget.future != null) {
final Object callbackIdentity = Object();
_activeCallbackIdentity = callbackIdentity;
widget.future.then<void>((T data) {
widget.future!.then<void>((T data) {
if (_activeCallbackIdentity == callbackIdentity) {
setState(() {
_snapshot = AsyncSnapshot<T>.withData(ConnectionState.done, data);
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/services.dart';
import 'framework.dart';
......@@ -152,8 +150,8 @@ class AutofillGroup extends StatefulWidget {
///
/// The [child] argument must not be null.
const AutofillGroup({
Key key,
@required this.child,
Key? key,
required this.child,
this.onDisposeAction = AutofillContextAction.commit,
}) : assert(child != null),
super(key: key);
......@@ -166,8 +164,8 @@ class AutofillGroup extends StatefulWidget {
///
/// * [EditableTextState], where this method is used to retrieve the closest
/// [AutofillGroupState].
static AutofillGroupState of(BuildContext context) {
final _AutofillScope scope = context.dependOnInheritedWidgetOfExactType<_AutofillScope>();
static AutofillGroupState? of(BuildContext context) {
final _AutofillScope? scope = context.dependOnInheritedWidgetOfExactType<_AutofillScope>();
return scope?._scope;
}
......@@ -214,12 +212,12 @@ class AutofillGroupState extends State<AutofillGroup> with AutofillScopeMixin {
bool _isTopmostAutofillGroup = false;
@override
AutofillClient getAutofillClient(String tag) => _clients[tag];
AutofillClient? getAutofillClient(String tag) => _clients[tag];
@override
Iterable<AutofillClient> get autofillClients {
return _clients.values
.where((AutofillClient client) => client?.textInputConfiguration?.autofillConfiguration != null);
.where((AutofillClient client) => client.textInputConfiguration.autofillConfiguration != null);
}
/// Adds the [AutofillClient] to this [AutofillGroup].
......@@ -289,15 +287,15 @@ class AutofillGroupState extends State<AutofillGroup> with AutofillScopeMixin {
class _AutofillScope extends InheritedWidget {
const _AutofillScope({
Key key,
Widget child,
AutofillGroupState autofillScopeState,
Key? key,
required Widget child,
AutofillGroupState? autofillScopeState,
}) : _scope = autofillScopeState,
super(key: key, child: child);
final AutofillGroupState _scope;
final AutofillGroupState? _scope;
AutofillGroup get client => _scope.widget;
AutofillGroup get client => _scope!.widget;
@override
bool updateShouldNotify(_AutofillScope old) => _scope != old._scope;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:async';
import 'package:flutter/foundation.dart';
......@@ -29,22 +27,22 @@ class AutomaticKeepAlive extends StatefulWidget {
/// Creates a widget that listens to [KeepAliveNotification]s and maintains a
/// [KeepAlive] widget appropriately.
const AutomaticKeepAlive({
Key key,
Key? key,
this.child,
}) : super(key: key);
/// The widget below this widget in the tree.
///
/// {@macro flutter.widgets.child}
final Widget child;
final Widget? child;
@override
_AutomaticKeepAliveState createState() => _AutomaticKeepAliveState();
}
class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
Map<Listenable, VoidCallback> _handles;
Widget _child;
Map<Listenable, VoidCallback>? _handles;
Widget? _child;
bool _keepingAlive = false;
@override
......@@ -62,15 +60,15 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
void _updateChild() {
_child = NotificationListener<KeepAliveNotification>(
onNotification: _addClient,
child: widget.child,
child: widget.child!,
);
}
@override
void dispose() {
if (_handles != null) {
for (final Listenable handle in _handles.keys)
handle.removeListener(_handles[handle]);
for (final Listenable handle in _handles!.keys)
handle.removeListener(_handles![handle]!);
}
super.dispose();
}
......@@ -78,12 +76,12 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
bool _addClient(KeepAliveNotification notification) {
final Listenable handle = notification.handle;
_handles ??= <Listenable, VoidCallback>{};
assert(!_handles.containsKey(handle));
_handles[handle] = _createCallback(handle);
handle.addListener(_handles[handle]);
assert(!_handles!.containsKey(handle));
_handles![handle] = _createCallback(handle);
handle.addListener(_handles![handle]!);
if (!_keepingAlive) {
_keepingAlive = true;
final ParentDataElement<KeepAliveParentDataMixin> childElement = _getChildElement();
final ParentDataElement<KeepAliveParentDataMixin>? childElement = _getChildElement();
if (childElement != null) {
// If the child already exists, update it synchronously.
_updateParentDataOfChild(childElement);
......@@ -91,13 +89,13 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
// If the child doesn't exist yet, we got called during the very first
// build of this subtree. Wait until the end of the frame to update
// the child when the child is guaranteed to be present.
SchedulerBinding.instance.addPostFrameCallback((Duration timeStamp) {
SchedulerBinding.instance!.addPostFrameCallback((Duration timeStamp) {
if (!mounted) {
return;
}
final ParentDataElement<KeepAliveParentDataMixin> childElement = _getChildElement();
final ParentDataElement<KeepAliveParentDataMixin>? childElement = _getChildElement();
assert(childElement != null);
_updateParentDataOfChild(childElement);
_updateParentDataOfChild(childElement!);
});
}
}
......@@ -108,10 +106,10 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
///
/// While this widget is guaranteed to have a child, this may return null if
/// the first build of that child has not completed yet.
ParentDataElement<KeepAliveParentDataMixin> _getChildElement() {
ParentDataElement<KeepAliveParentDataMixin>? _getChildElement() {
assert(mounted);
final Element element = context as Element;
Element childElement;
Element? childElement;
// We use Element.visitChildren rather than context.visitChildElements
// because we might be called during build, and context.visitChildElements
// verifies that it is not called during build. Element.visitChildren does
......@@ -135,7 +133,7 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
childElement = child;
});
assert(childElement == null || childElement is ParentDataElement<KeepAliveParentDataMixin>);
return childElement as ParentDataElement<KeepAliveParentDataMixin>;
return childElement as ParentDataElement<KeepAliveParentDataMixin>?;
}
void _updateParentDataOfChild(ParentDataElement<KeepAliveParentDataMixin> childElement) {
......@@ -155,9 +153,9 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
}
return true;
}());
_handles.remove(handle);
if (_handles.isEmpty) {
if (SchedulerBinding.instance.schedulerPhase.index < SchedulerPhase.persistentCallbacks.index) {
_handles!.remove(handle);
if (_handles!.isEmpty) {
if (SchedulerBinding.instance!.schedulerPhase.index < SchedulerPhase.persistentCallbacks.index) {
// Build/layout haven't started yet so let's just schedule this for
// the next frame.
setState(() { _keepingAlive = false; });
......@@ -213,7 +211,7 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
// avoid it if possible.
_keepingAlive = false;
scheduleMicrotask(() {
if (mounted && _handles.isEmpty) {
if (mounted && _handles!.isEmpty) {
// If mounted is false, we went away as well, so there's nothing to do.
// If _handles is no longer empty, then another client (or the same
// client in a new place) registered itself before we had a chance to
......@@ -233,7 +231,7 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
assert(_child != null);
return KeepAlive(
keepAlive: _keepingAlive,
child: _child,
child: _child!,
);
}
......@@ -246,7 +244,7 @@ class _AutomaticKeepAliveState extends State<AutomaticKeepAlive> {
'handles',
_handles,
description: _handles != null ?
'${_handles.length} active client${ _handles.length == 1 ? "" : "s" }' :
'${_handles!.length} active client${ _handles!.length == 1 ? "" : "s" }' :
null,
ifNull: 'no notifications ever received',
));
......@@ -330,8 +328,7 @@ class KeepAliveHandle extends ChangeNotifier {
/// with [State] subclasses.
///
/// Subclasses must implement [wantKeepAlive], and their [build] methods must
/// call `super.build` (the return value will always return null, and should be
/// ignored).
/// call `super.build` (though the return value should be ignored).
///
/// Then, whenever [wantKeepAlive]'s value changes (or might change), the
/// subclass should call [updateKeepAlive].
......@@ -345,16 +342,16 @@ class KeepAliveHandle extends ChangeNotifier {
/// * [KeepAliveNotification], the notifications sent by this mixin.
@optionalTypeArgs
mixin AutomaticKeepAliveClientMixin<T extends StatefulWidget> on State<T> {
KeepAliveHandle _keepAliveHandle;
KeepAliveHandle? _keepAliveHandle;
void _ensureKeepAlive() {
assert(_keepAliveHandle == null);
_keepAliveHandle = KeepAliveHandle();
KeepAliveNotification(_keepAliveHandle).dispatch(context);
KeepAliveNotification(_keepAliveHandle!).dispatch(context);
}
void _releaseKeepAlive() {
_keepAliveHandle.release();
_keepAliveHandle!.release();
_keepAliveHandle = null;
}
......@@ -397,6 +394,18 @@ mixin AutomaticKeepAliveClientMixin<T extends StatefulWidget> on State<T> {
Widget build(BuildContext context) {
if (wantKeepAlive && _keepAliveHandle == null)
_ensureKeepAlive();
return null;
return const _NullWidget();
}
}
class _NullWidget extends StatelessWidget {
const _NullWidget();
@override
Widget build(BuildContext context) {
throw FlutterError(
'Widgets that mix AutomaticKeepAliveClientMixin into their State must '
'call super.build() but must ignore the return value of the superclass.'
);
}
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:math' as math;
import 'package:flutter/foundation.dart';
......@@ -61,10 +59,10 @@ class BannerPainter extends CustomPainter {
/// The [message], [textDirection], [location], and [layoutDirection]
/// arguments must not be null.
BannerPainter({
@required this.message,
@required this.textDirection,
@required this.location,
@required this.layoutDirection,
required this.message,
required this.textDirection,
required this.location,
required this.layoutDirection,
this.color = _kColor,
this.textStyle = _kTextStyle,
}) : assert(message != null),
......@@ -72,7 +70,7 @@ class BannerPainter extends CustomPainter {
assert(location != null),
assert(color != null),
assert(textStyle != null),
super(repaint: PaintingBinding.instance.systemFonts);
super(repaint: PaintingBinding.instance!.systemFonts);
/// The message to show in the banner.
final String message;
......@@ -120,9 +118,9 @@ class BannerPainter extends CustomPainter {
);
bool _prepared = false;
TextPainter _textPainter;
Paint _paintShadow;
Paint _paintBanner;
late TextPainter _textPainter;
late Paint _paintShadow;
late Paint _paintBanner;
void _prepare() {
_paintShadow = _shadow.toPaint();
......@@ -176,7 +174,6 @@ class BannerPainter extends CustomPainter {
case BannerLocation.topStart:
return width;
}
break;
case TextDirection.ltr:
switch (location) {
case BannerLocation.bottomEnd:
......@@ -188,9 +185,7 @@ class BannerPainter extends CustomPainter {
case BannerLocation.topStart:
return 0.0;
}
break;
}
return null;
}
double _translationY(double height) {
......@@ -203,7 +198,6 @@ class BannerPainter extends CustomPainter {
case BannerLocation.topEnd:
return 0.0;
}
return null;
}
double get _rotation {
......@@ -219,7 +213,6 @@ class BannerPainter extends CustomPainter {
case BannerLocation.topStart:
return math.pi / 4.0;
}
break;
case TextDirection.ltr:
switch (location) {
case BannerLocation.bottomStart:
......@@ -229,9 +222,7 @@ class BannerPainter extends CustomPainter {
case BannerLocation.topStart:
return -math.pi / 4.0;
}
break;
}
return null;
}
}
......@@ -249,11 +240,11 @@ class Banner extends StatelessWidget {
///
/// The [message] and [location] arguments must not be null.
const Banner({
Key key,
Key? key,
this.child,
@required this.message,
required this.message,
this.textDirection,
@required this.location,
required this.location,
this.layoutDirection,
this.color = _kColor,
this.textStyle = _kTextStyle,
......@@ -266,7 +257,7 @@ class Banner extends StatelessWidget {
/// The widget to show behind the banner.
///
/// {@macro flutter.widgets.child}
final Widget child;
final Widget? child;
/// The message to show in the banner.
final String message;
......@@ -285,7 +276,7 @@ class Banner extends StatelessWidget {
/// See also:
///
/// * [layoutDirection], which controls the interpretation of the [location].
final TextDirection textDirection;
final TextDirection? textDirection;
/// Where to show the banner (e.g., the upper right corner).
final BannerLocation location;
......@@ -299,7 +290,7 @@ class Banner extends StatelessWidget {
/// See also:
///
/// * [textDirection], which controls the reading direction of the [message].
final TextDirection layoutDirection;
final TextDirection? layoutDirection;
/// The color of the banner.
final Color color;
......@@ -313,9 +304,9 @@ class Banner extends StatelessWidget {
return CustomPaint(
foregroundPainter: BannerPainter(
message: message,
textDirection: textDirection ?? Directionality.of(context),
textDirection: textDirection ?? Directionality.of(context)!,
location: location,
layoutDirection: layoutDirection ?? Directionality.of(context),
layoutDirection: layoutDirection ?? Directionality.of(context)!,
color: color,
textStyle: textStyle,
),
......@@ -331,7 +322,7 @@ class Banner extends StatelessWidget {
properties.add(EnumProperty<BannerLocation>('location', location));
properties.add(EnumProperty<TextDirection>('layoutDirection', layoutDirection, defaultValue: null));
properties.add(ColorProperty('color', color, showName: false));
textStyle?.debugFillProperties(properties, prefix: 'text ');
textStyle.debugFillProperties(properties, prefix: 'text ');
}
}
......@@ -341,8 +332,8 @@ class Banner extends StatelessWidget {
class CheckedModeBanner extends StatelessWidget {
/// Creates a const checked mode banner.
const CheckedModeBanner({
Key key,
@required this.child,
Key? key,
required this.child,
}) : super(key: key);
/// The widget to show behind the banner.
......
This diff is collapsed.
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui' show Color;
import 'framework.dart';
......@@ -25,14 +23,14 @@ class BottomNavigationBarItem {
///
/// The argument [icon] should not be null and the argument [title] should not be null when used in a Material Design's [BottomNavigationBar].
const BottomNavigationBarItem({
@required this.icon,
required this.icon,
@Deprecated(
'Use "label" instead, as it allows for an improved text-scaling experience. '
'This feature was deprecated after v1.19.0.'
)
this.title,
this.label,
Widget activeIcon,
Widget? activeIcon,
this.backgroundColor,
}) : activeIcon = activeIcon ?? icon,
assert(label == null || title == null),
......@@ -75,14 +73,14 @@ class BottomNavigationBarItem {
'Use "label" instead, as it allows for an improved text-scaling experience. '
'This feature was deprecated after v1.19.0.'
)
final Widget title;
final Widget? title;
/// The text label for this [BottomNavigationBarItem].
///
/// This will be used to create a [Text] widget to put in the bottom navigation bar,
/// and in Material Design [BottomNavigationBar]s, this will be used to display
/// a tooltip on long press of an item in the [BottomNavigationBar].
final String label;
final String? label;
/// The color of the background radial animation for material [BottomNavigationBar].
///
......@@ -97,5 +95,5 @@ class BottomNavigationBarItem {
///
/// * [Icon.color] and [ImageIcon.color] to control the foreground color of
/// the icons themselves.
final Color backgroundColor;
final Color? backgroundColor;
}
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui';
import 'package:flutter/foundation.dart';
......@@ -19,7 +17,7 @@ class ColorFiltered extends SingleChildRenderObjectWidget {
/// Creates a widget that applies a [ColorFilter] to its child.
///
/// The [colorFilter] must not be null.
const ColorFiltered({@required this.colorFilter, Widget child, Key key})
const ColorFiltered({required this.colorFilter, Widget? child, Key? key})
: assert(colorFilter != null),
super(key: key, child: child);
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
/// The minimum dimension of any interactive region according to the Material
/// guidelines.
///
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'package:flutter/foundation.dart';
import 'package:flutter/painting.dart';
import 'package:flutter/rendering.dart';
......@@ -61,10 +59,10 @@ class DecoratedBox extends SingleChildRenderObjectWidget {
/// The [decoration] and [position] arguments must not be null. By default the
/// decoration paints behind the child.
const DecoratedBox({
Key key,
@required this.decoration,
Key? key,
required this.decoration,
this.position = DecorationPosition.background,
Widget child,
Widget? child,
}) : assert(decoration != null),
assert(position != null),
super(key: key, child: child);
......@@ -98,19 +96,15 @@ class DecoratedBox extends SingleChildRenderObjectWidget {
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
String label;
if (position != null) {
switch (position) {
case DecorationPosition.background:
label = 'bg';
break;
case DecorationPosition.foreground:
label = 'fg';
break;
}
} else {
label = 'decoration';
switch (position) {
case DecorationPosition.background:
label = 'bg';
break;
case DecorationPosition.foreground:
label = 'fg';
break;
}
properties.add(EnumProperty<DecorationPosition>('position', position, level: position != null ? DiagnosticLevel.hidden : DiagnosticLevel.info));
properties.add(EnumProperty<DecorationPosition>('position', position, level: DiagnosticLevel.hidden));
properties.add(DiagnosticsProperty<Decoration>(
label,
decoration,
......@@ -263,15 +257,15 @@ class Container extends StatelessWidget {
/// color. To supply a decoration with a color, use `decoration:
/// BoxDecoration(color: color)`.
Container({
Key key,
Key? key,
this.alignment,
this.padding,
this.color,
this.decoration,
this.foregroundDecoration,
double width,
double height,
BoxConstraints constraints,
double? width,
double? height,
BoxConstraints? constraints,
this.margin,
this.transform,
this.child,
......@@ -301,7 +295,7 @@ class Container extends StatelessWidget {
/// will attempt to be as small as possible.
///
/// {@macro flutter.widgets.child}
final Widget child;
final Widget? child;
/// Align the [child] within the container.
///
......@@ -317,14 +311,14 @@ class Container extends StatelessWidget {
/// specify an [AlignmentGeometry].
/// * [AlignmentDirectional], like [Alignment] for specifying alignments
/// relative to text direction.
final AlignmentGeometry alignment;
final AlignmentGeometry? alignment;
/// Empty space to inscribe inside the [decoration]. The [child], if any, is
/// placed inside this padding.
///
/// This padding is in addition to any padding inherent in the [decoration];
/// see [Decoration.padding].
final EdgeInsetsGeometry padding;
final EdgeInsetsGeometry? padding;
/// The color to paint behind the [child].
///
......@@ -335,7 +329,7 @@ class Container extends StatelessWidget {
/// If the [decoration] is used, this property must be null. A background
/// color may still be painted by the [decoration] even if this property is
/// null.
final Color color;
final Color? color;
/// The decoration to paint behind the [child].
///
......@@ -343,10 +337,10 @@ class Container extends StatelessWidget {
///
/// The [child] is not clipped to the decoration. To clip a child to the shape
/// of a particular [ShapeDecoration], consider using a [ClipPath] widget.
final Decoration decoration;
final Decoration? decoration;
/// The decoration to paint in front of the [child].
final Decoration foregroundDecoration;
final Decoration? foregroundDecoration;
/// Additional constraints to apply to the child.
///
......@@ -354,13 +348,13 @@ class Container extends StatelessWidget {
/// `constraints` argument to set this property.
///
/// The [padding] goes inside the constraints.
final BoxConstraints constraints;
final BoxConstraints? constraints;
/// Empty space to surround the [decoration] and [child].
final EdgeInsetsGeometry margin;
final EdgeInsetsGeometry? margin;
/// The transformation matrix to apply before painting the container.
final Matrix4 transform;
final Matrix4? transform;
/// The clip behavior when [Container.decoration] is not null.
///
......@@ -372,20 +366,20 @@ class Container extends StatelessWidget {
/// method throws an [UnsupportedError].)
final Clip clipBehavior;
EdgeInsetsGeometry get _paddingIncludingDecoration {
if (decoration == null || decoration.padding == null)
EdgeInsetsGeometry? get _paddingIncludingDecoration {
if (decoration == null || decoration!.padding == null)
return padding;
final EdgeInsetsGeometry decorationPadding = decoration.padding;
final EdgeInsetsGeometry? decorationPadding = decoration!.padding;
if (padding == null)
return decorationPadding;
return padding.add(decorationPadding);
return padding!.add(decorationPadding!);
}
@override
Widget build(BuildContext context) {
Widget current = child;
Widget? current = child;
if (child == null && (constraints == null || !constraints.isTight)) {
if (child == null && (constraints == null || !constraints!.isTight)) {
current = LimitedBox(
maxWidth: 0.0,
maxHeight: 0.0,
......@@ -394,21 +388,21 @@ class Container extends StatelessWidget {
}
if (alignment != null)
current = Align(alignment: alignment, child: current);
current = Align(alignment: alignment!, child: current);
final EdgeInsetsGeometry effectivePadding = _paddingIncludingDecoration;
final EdgeInsetsGeometry? effectivePadding = _paddingIncludingDecoration;
if (effectivePadding != null)
current = Padding(padding: effectivePadding, child: current);
if (color != null)
current = ColoredBox(color: color, child: current);
current = ColoredBox(color: color!, child: current);
if (clipBehavior != Clip.none) {
assert(decoration != null);
current = ClipPath(
clipper: _DecorationClipper(
textDirection: Directionality.of(context),
decoration: decoration
decoration: decoration!,
),
clipBehavior: clipBehavior,
child: current,
......@@ -416,26 +410,26 @@ class Container extends StatelessWidget {
}
if (decoration != null)
current = DecoratedBox(decoration: decoration, child: current);
current = DecoratedBox(decoration: decoration!, child: current);
if (foregroundDecoration != null) {
current = DecoratedBox(
decoration: foregroundDecoration,
decoration: foregroundDecoration!,
position: DecorationPosition.foreground,
child: current,
);
}
if (constraints != null)
current = ConstrainedBox(constraints: constraints, child: current);
current = ConstrainedBox(constraints: constraints!, child: current);
if (margin != null)
current = Padding(padding: margin, child: current);
current = Padding(padding: margin!, child: current);
if (transform != null)
current = Transform(transform: transform, child: current);
current = Transform(transform: transform!, child: current);
return current;
return current!;
}
@override
......@@ -458,8 +452,8 @@ class Container extends StatelessWidget {
/// A clipper that uses [Decoration.getClipPath] to clip.
class _DecorationClipper extends CustomClipper<Path> {
_DecorationClipper({
TextDirection textDirection,
@required this.decoration
TextDirection? textDirection,
required this.decoration
}) : assert(decoration != null),
textDirection = textDirection ?? TextDirection.ltr;
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:collection';
import 'dart:developer' show Timeline; // to disambiguate reference in dartdocs below
......@@ -55,7 +53,7 @@ typedef RebuildDirtyWidgetCallback = void Function(Element e, bool builtOnce);
/// rebuilds occurred when the
/// `ext.flutter.inspector.trackRebuildDirtyWidgets` service extension is
/// enabled.
RebuildDirtyWidgetCallback debugOnRebuildDirtyWidget;
RebuildDirtyWidgetCallback? debugOnRebuildDirtyWidget;
/// Log all calls to [BuildOwner.buildScope].
///
......@@ -110,13 +108,13 @@ bool debugProfileBuildsEnabled = false;
/// Show banners for deprecated widgets.
bool debugHighlightDeprecatedWidgets = false;
Key _firstNonUniqueKey(Iterable<Widget> widgets) {
Key? _firstNonUniqueKey(Iterable<Widget> widgets) {
final Set<Key> keySet = HashSet<Key>();
for (final Widget widget in widgets) {
assert(widget != null);
if (widget.key == null)
continue;
if (!keySet.add(widget.key))
if (!keySet.add(widget.key!))
return widget.key;
}
return null;
......@@ -138,7 +136,7 @@ Key _firstNonUniqueKey(Iterable<Widget> widgets) {
/// Does nothing if asserts are disabled. Always returns true.
bool debugChildrenHaveDuplicateKeys(Widget parent, Iterable<Widget> children) {
assert(() {
final Key nonUniqueKey = _firstNonUniqueKey(children);
final Key? nonUniqueKey = _firstNonUniqueKey(children);
if (nonUniqueKey != null) {
throw FlutterError(
'Duplicate keys found.\n'
......@@ -165,7 +163,7 @@ bool debugChildrenHaveDuplicateKeys(Widget parent, Iterable<Widget> children) {
/// Does nothing if asserts are disabled. Always returns true.
bool debugItemsHaveDuplicateKeys(Iterable<Widget> items) {
assert(() {
final Key nonUniqueKey = _firstNonUniqueKey(items);
final Key? nonUniqueKey = _firstNonUniqueKey(items);
if (nonUniqueKey != null)
throw FlutterError('Duplicate key found: $nonUniqueKey.');
return true;
......@@ -262,7 +260,7 @@ bool debugCheckHasMediaQuery(BuildContext context) {
/// with the more generic advice regarding [Directionality].
///
/// Does nothing if asserts are disabled. Always returns true.
bool debugCheckHasDirectionality(BuildContext context, { String why, String hint, String alternative }) {
bool debugCheckHasDirectionality(BuildContext context, { String? why, String? hint, String? alternative }) {
assert(() {
if (context.widget is! Directionality && context.findAncestorWidgetOfExactType<Directionality>() == null) {
why = why == null ? '' : ' $why';
......@@ -296,7 +294,7 @@ bool debugCheckHasDirectionality(BuildContext context, { String why, String hint
/// function returned a non-null value, as typically required.
///
/// Does nothing when asserts are disabled.
void debugWidgetBuilderValue(Widget widget, Widget built) {
void debugWidgetBuilderValue(Widget widget, Widget? built) {
assert(() {
if (built == null) {
throw FlutterError.fromParts(<DiagnosticsNode>[
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'framework.dart';
/// Provides non-leaking access to a [BuildContext].
......@@ -31,21 +29,21 @@ class DisposableBuildContext<T extends State> {
/// The [State] must not be null, and [State.mounted] must be true.
DisposableBuildContext(this._state)
: assert(_state != null),
assert(_state.mounted, 'A DisposableBuildContext was given a BuildContext for an Element that is not mounted.');
assert(_state!.mounted, 'A DisposableBuildContext was given a BuildContext for an Element that is not mounted.');
T _state;
T? _state;
/// Provides safe access to the build context.
///
/// If [dispose] has been called, will return null.
///
/// Otherwise, asserts the [_state] is still mounted and returns its context.
BuildContext get context {
BuildContext? get context {
assert(_debugValidate());
if (_state == null) {
return null;
}
return _state.context;
return _state!.context;
}
/// Called from asserts or tests to determine whether this object is in a
......@@ -55,7 +53,7 @@ class DisposableBuildContext<T extends State> {
/// but the state this is tracking is unmounted.
bool _debugValidate() {
assert(
_state == null || _state.mounted,
_state == null || _state!.mounted,
'A DisposableBuildContext tried to access the BuildContext of a disposed '
'State object. This can happen when the creator of this '
'DisposableBuildContext fails to call dispose when it is disposed.',
......
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'basic.dart';
import 'framework.dart';
......@@ -15,8 +13,8 @@ import 'framework.dart';
/// The `animation` provided to the builder always runs forward from 0.0 to 1.0.
typedef AnimatedTransitionBuilder = Widget Function(
BuildContext context,
Animation<double> animation,
Widget child,
Animation<double?> animation,
Widget? child,
);
/// A transition builder that animates its [child] based on the
......@@ -38,10 +36,10 @@ class DualTransitionBuilder extends StatefulWidget {
/// The [animation], [forwardBuilder], and [reverseBuilder] arguments are
/// required and must not be null.
const DualTransitionBuilder({
Key key,
@required this.animation,
@required this.forwardBuilder,
@required this.reverseBuilder,
Key? key,
required this.animation,
required this.forwardBuilder,
required this.reverseBuilder,
this.child,
}) : assert(animation != null),
assert(forwardBuilder != null),
......@@ -89,14 +87,14 @@ class DualTransitionBuilder extends StatefulWidget {
///
/// This child widget will be wrapped by the transitions built by
/// [forwardBuilder] and [reverseBuilder].
final Widget child;
final Widget? child;
@override
State<DualTransitionBuilder> createState() => _DualTransitionBuilderState();
}
class _DualTransitionBuilderState extends State<DualTransitionBuilder> {
AnimationStatus _effectiveAnimationStatus;
late AnimationStatus _effectiveAnimationStatus;
final ProxyAnimation _forwardAnimation = ProxyAnimation();
final ProxyAnimation _reverseAnimation = ProxyAnimation();
......@@ -134,8 +132,8 @@ class _DualTransitionBuilderState extends State<DualTransitionBuilder> {
// yield a disjoint experience since the forward and reverse transitions are
// very different.
AnimationStatus _calculateEffectiveAnimationStatus({
@required AnimationStatus lastEffective,
@required AnimationStatus current,
required AnimationStatus lastEffective,
required AnimationStatus current,
}) {
assert(current != null);
assert(lastEffective != null);
......@@ -152,7 +150,6 @@ class _DualTransitionBuilderState extends State<DualTransitionBuilder> {
case AnimationStatus.reverse:
return lastEffective;
}
break;
case AnimationStatus.reverse:
switch (lastEffective) {
case AnimationStatus.dismissed:
......@@ -162,9 +159,7 @@ class _DualTransitionBuilderState extends State<DualTransitionBuilder> {
case AnimationStatus.forward:
return lastEffective;
}
break;
}
return null; // unreachable
}
void _updateAnimations() {
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// @dart = 2.8
import 'dart:ui';
import 'package:flutter/foundation.dart';
......@@ -24,9 +22,9 @@ class ImageFiltered extends SingleChildRenderObjectWidget {
///
/// The [imageFilter] must not be null.
const ImageFiltered({
Key key,
@required this.imageFilter,
Widget child,
Key? key,
required this.imageFilter,
Widget? child,
}) : assert(imageFilter != null),
super(key: key, child: child);
......@@ -73,7 +71,7 @@ class _ImageFilterRenderObject extends RenderProxyBox {
final ImageFilterLayer filterLayer = layer as ImageFilterLayer;
filterLayer.imageFilter = imageFilter;
}
context.pushLayer(layer, super.paint, offset);
context.pushLayer(layer!, super.paint, offset);
assert(layer != null);
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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